当前位置:网站首页>First knowledge of OpenGL es learning (1)
First knowledge of OpenGL es learning (1)
2022-07-06 07:05:00 【Unlimited exchange】
1. know OpenGL ES
OpenGL It's cross platform 2D/3D graphics API, and OpenGL ES It is an extended version based on the former , Suitable for embedded devices such as mobile phones . It has the following versions :
edition | explain |
---|---|
OpenGL ES 1.0 | 2003 Released in |
OpenGL ES 1.1 | Supports multiple textures , Vertex buffer object, etc |
OpenGL ES 2.0 | 2007 Released in , be based on OpenGL 2.0, Deleted 1.x Fixed pipeline in (pipeline), Provide programmable pipelines |
OpenGL ES 3.0 | 2012 Released in , Backward compatibility 2.x |
OpenGL ES 3.1 | 2014 Released in |
OpenGL ES 3.2 | 2015 Released in |
OpenGL ES 1.x and OpenGL ES2.0 Incompatible , Are two completely different implementations .
OpenGL EX 1.x Only fixed pipeline rendering is supported , It can be firmware support or software emulation , But the rendering ability is limited .
OpenGL EX 2.X Using programmable rendering pipeline , Improved rendering ability . But the difficulty of programming has also increased , And it is required that there must be corresponding GPU Hardware support .
The above figure 3-16 Sum graph 3-21 Namely OpenGL 1.x and OpenGL 2.x Rendering pipeline process diagram .“ Transform and lighting ”---->“ Vertex shader ”
“ Texture environment and color summation ”、“ Fog ”、“Alpha velocity measurement ”---->“ Chip shader ”
This series will focus on OpenGL ES2.x
2. First time to know OpenGL ES2.x Program appearance
I'm getting to know you OpenGL ES After the foundation , Here is an entry level Demo( The official website of this program also has similar learning ). Comments have been added to the code , It can better help you get started .
2.1 design sketch
2.2 Tool class ShaderUtil.java
public class ShaderUtil {
private static final String TAG = "ShaderUtil";
/**
* Load shaders encoded into GPU And compile
*
* @param shaderType Shader type
* @param source Shader script string
* @return
*/
public static 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, "loadShader: ES20_ERROR,Could not compile shader " + shaderType + ";");
Log.e(TAG, "loadShader: ES20_ERROR,shader = " + GLES20.glGetShaderInfoLog(shader));
GLES20.glDeleteShader(shader);
shader = 0;
}
}
return shader;
}
/**
* Create shader program
*
* @param vertexSource
* @param fragmentSource
* @return
*/
public static int createProgram(String vertexSource, String fragmentSource) {
// Load vertex shaders
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
if (vertexShader == 0) {
return 0;
}
// Load the slice shader
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, "createProgram: ES20_ERROR,Could not link program");
Log.e(TAG, "createProgram: ES20_ERROR,program = " + GLES20.glGetProgramInfoLog(program));
GLES20.glDeleteProgram(program);
program = 0;
}
}
return program;
}
/**
* Check whether there is a wrong method in each operation
*
* @param op
*/
public static void checkGLError(String op) {
int error;
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Log.d(TAG, ">>>>>> " + op + " :glError " + error);
throw new RuntimeException(op + ":glError " + error);
}
}
/**
* from sh Load shader contents in the script
*
* @param fname
* @param resources
* @return
*/
public static String loadFromAssetsFile(String fname, Resources resources) {
String result = null;
try {
InputStream in = resources.getAssets().open(fname);
int ch = 0;
ByteArrayOutputStream baos = new ByteArrayOutputStream();
while ((ch = in.read()) != -1) {
baos.write(ch);// The obtained information is written to the stream
}
byte[] buffer = baos.toByteArray();
baos.close();
in.close();
result = new String(buffer, "UTF-8");
result = result.replaceAll("\\r\\n", "\n");
} catch (IOException e) {
e.printStackTrace();
}
Log.d(TAG, "loadFromAssetsFile: result = " + result);
return result;
}
}
2.3 triangle Triangle
public class Triangle {
public static float[] mProjMatrix = new float[16];//4x4 Projection matrix
public static float[] mVMatrix = new float[16];// Parameter matrix of camera position orientation
public static float[] mMvPMatrix;// Total transformation matrix
private int program;// Custom render pipeline shader program id
private int muMVPMatrixHandle;// Total transformation matrix reference
private int maPositionHandle;// Vertex position attribute reference
private int maColorHandle;// Vertex color attribute reference
private String mVertexShader;// Vertex shader code script
private String mFragmentShader;// Fragment shader code script
private static float[] mMMatrix = new float[16];// Specific objects 3D Transformation matrix , Including rotation 、 translation 、 The zoom
private FloatBuffer mVertexBuffer;// Vertex coordinate data buffer
private FloatBuffer mColorBuffer;// Vertex shading data buffer
private int vCount = 0;// Number of vertices
public float xAngle = 0;// Around the X Angle of axis rotation
public Triangle(MyTDView myTDView) {
initVertexData();
initShader(myTDView);
}
/**
* Initialize shaders
* @param myTDView
*/
private void initShader(MyTDView myTDView) {
mVertexShader = ShaderUtil.loadFromAssetsFile("vertex.sh", myTDView.getResources());
mFragmentShader = ShaderUtil.loadFromAssetsFile("frag.sh", myTDView.getResources());
program = ShaderUtil.createProgram(mVertexShader, mFragmentShader);
maPositionHandle = GLES20.glGetAttribLocation(program, "aPosition");
maColorHandle = GLES20.glGetAttribLocation(program, "aColor");
muMVPMatrixHandle = GLES20.glGetUniformLocation(program, "uMVPMatrix");
}
/**
* Draw triangle
*/
public void drawSelf() {
GLES20.glUseProgram(program);
Matrix.setRotateM(mMMatrix, 0, 0, 0, 1, 0);// Initialize the transformation matrix
Matrix.translateM(mMMatrix, 0, 0, 0, 1);// Set along Z Positive displacement of shaft
Matrix.rotateM(mMMatrix, 0, xAngle, 1, 0, 0);// Set winding X Shaft rotation
GLES20.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, Triangle.getFinalMatrix(mMMatrix), 0);
GLES20.glVertexAttribPointer(maPositionHandle, 3, GLES20.GL_FLOAT, false, 3 * 4, mVertexBuffer);
GLES20.glVertexAttribPointer(maColorHandle, 4, GLES20.GL_FLOAT, false, 4 * 4, mColorBuffer);
GLES20.glEnableVertexAttribArray(maPositionHandle);
GLES20.glEnableVertexAttribArray(maColorHandle);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, vCount);
}
/**
* Initialize vertex data
*/
private void initVertexData() {
vCount = 3;
final float UNIT_SIZE = 0.2f;// Set unit length
// An array of vertex coordinates
float vertices[] = new float[]{
-4 * UNIT_SIZE, 0, 0,
0, -4 * UNIT_SIZE, 0,
4 * UNIT_SIZE, 0, 0
};
ByteBuffer vbb = ByteBuffer.allocateDirect(vertices.length * 4);
vbb.order(ByteOrder.nativeOrder());// Set byte order to local operating system order
mVertexBuffer = vbb.asFloatBuffer();// Convert to floating-point buffer
mVertexBuffer.put(vertices);// Write data in the buffer
mVertexBuffer.position(0);// Set buffer start position
// Vertex color array
float colors[] = new float[]{
1, 1, 1, 0,
0, 0, 1, 0,
0, 1, 0, 0
};
ByteBuffer cbb = ByteBuffer.allocateDirect(colors.length * 4);
cbb.order(ByteOrder.nativeOrder());
mColorBuffer = cbb.asFloatBuffer();
mColorBuffer.put(colors);
mColorBuffer.position(0);
}
/**
* The final transformation matrix
*
* @param spec
* @return
*/
public static float[] getFinalMatrix(float[] spec) {
// Initialize the total transformation matrix
mMvPMatrix = new float[16];
Matrix.multiplyMM(mMvPMatrix, 0, mVMatrix, 0, spec, 0);
Matrix.multiplyMM(mMvPMatrix, 0, mProjMatrix, 0, mMvPMatrix, 0);
return mMvPMatrix;
}
}
2.4 Rendering class MyTDView
GLSurfaceView and GLSurfaceView.Render Use
public class MyTDView extends GLSurfaceView {
private static final String TAG = "MyTDView";
// The angle of each triangle rotation
private final float ANGLE_SPAN = 0.375f;
// Threads
private RotateThread mRotateThread;
// Custom renderer
private SceneRenderer mSceneRenderer;
public MyTDView(Context context) {
super(context);
// Use OpenGLES2.0
this.setEGLContextClientVersion(2);
mSceneRenderer = new SceneRenderer();
this.setRenderer(mSceneRenderer);
this.setRenderMode(GLSurfaceView.RENDERMODE_CONTINUOUSLY);
}
private class SceneRenderer implements GLSurfaceView.Renderer {
Triangle mTriangle;
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0, 0, 0, 1.0f);// Set the screen background color
mTriangle = new Triangle(MyTDView.this);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
mRotateThread = new RotateThread();
mRotateThread.start();
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
GLES20.glViewport(0, 0, width, height);// Set up the viewport
float ratio = width / height;
// Set perspective projection
Matrix.frustumM(Triangle.mProjMatrix, 0, -ratio, ratio, -1, 1, 1, 10);
// Set up the camera
Matrix.setLookAtM(Triangle.mVMatrix, 0, 0, 0, 3,
0f, 0f, 0f, 0f, 1.0f, 0.0f);
}
@Override
public void onDrawFrame(GL10 gl) {
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
mTriangle.drawSelf();
}
}
private class RotateThread extends Thread {
// Set the cycle identification bit
public boolean flag = true;
@Override
public void run() {
super.run();
while (flag) {
mSceneRenderer.mTriangle.xAngle = mSceneRenderer.mTriangle.xAngle + ANGLE_SPAN;
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
2.5 Vertex shader and slice shader code
Vertex shader and slice shader resources are placed in assets Under the table of contents . The following is used in this case :
2.5.1 frag.sh
precision mediump float;
varying vec4 vColor;
void main(){
gl_FragColor = vColor;
}
2.5.2 vertex.sh Vertex shader
uniform mat4 uMVPMatrix;// Total transformation matrix
attribute vec3 aPosition;// Vertex Position
attribute vec4 aColor;// Vertex color
varying vec4 vColor;// Mutable variables passed to the slice shader
void main(){
gl_Position = uMVPMatrix * vec4(aPosition,1);// Calculate the position of the vertex drawn this time according to the total transformation matrix
vColor = aColor;
}
2.6 other
public class MainActivity extends AppCompatActivity {
private MyTDView mTDView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
mTDView = new MyTDView(this);
mTDView.requestFocus();
mTDView.setFocusableInTouchMode(true);
setContentView(mTDView);
}
@Override
protected void onResume() {
super.onResume();
mTDView.onResume();
}
@Override
protected void onPause() {
super.onPause();
mTDView.onPause();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
}
This sample program can be run directly , See the effect .
【 Reference resources 】
- https://www.khronos.org/opengles/
- 《OpenGL ES Application development practice guide Android volume Kevin Brothaler》
- https://en.wikipedia.org/wiki/OpenGL_ES
- https://developer.android.google.cn/guide/topics/graphics/opengl
- https://developer.android.google.cn/training/graphics/opengl
- Android3D Game development technology dictionary OpenGL ES 2.0
边栏推荐
- Simple use of MySQL database: add, delete, modify and query
- 【Hot100】739. Daily temperature
- Map of mL: Based on the adult census income two classification prediction data set (whether the predicted annual income exceeds 50K), use the map value to realize the interpretable case of xgboost mod
- C language_ Double create, pre insert, post insert, traverse, delete
- 中青看点阅读新闻
- Chapter 7 - thread pool of shared model
- 升级版手机检测微信工具小程序源码-支持多种流量主模式
- Explain in detail the functions and underlying implementation logic of the groups sets statement in SQL
- LeetCode 78:子集
- [server data recovery] case of offline data recovery of two hard disks of IBM server RAID5
猜你喜欢
leetcode1020. Number of enclaves (medium)
巴比特 | 元宇宙每日必读:中国互联网企业涌入元宇宙的群像:“只有各种求生欲,没有前瞻创新的雄心”...
CDN acceleration and cracking anti-theft chain function
19. Actual memory management of segment page combination
Misc of BUU (update from time to time)
Leetcode35. search the insertion position (simple, find the insertion position, different writing methods)
1189. Maximum number of "balloons"
How to reconstruct the class explosion caused by m*n strategies?
leetcode704. 二分查找(查找某个元素,简单,不同写法)
Huawei equipment configuration ospf-bgp linkage
随机推荐
TS Basics
Depth residual network
Introduction to ros2 installation and basic knowledge
AttributeError: Can‘t get attribute ‘SPPF‘ on <module ‘models. common‘ from ‘/home/yolov5/models/comm
[server data recovery] case of offline data recovery of two hard disks of IBM server RAID5
因高额网络费用,Arbitrum 奥德赛活动暂停,Nitro 发行迫在眉睫
After sharing the clone remote project, NPM install reports an error - CB () never called! This is an error with npm itself.
Due to high network costs, arbitrum Odyssey activities are suspended, and nitro release is imminent
Leetcode daily question (1870. minimum speed to arrive on time)
19.段页结合的实际内存管理
Uncaught typeerror: cannot red properties of undefined (reading 'beforeeach') solution
Practical guidance for interface automation testing (Part I): what preparations should be made for interface automation
The author is dead? AI is conquering mankind with art
BIO模型实现多人聊天
微信公众号无限回调授权系统源码 全网首发
树莓派串口登录与SSH登录方法
Development of entity developer database application
Every API has its foundation when a building rises from the ground
librosa音频处理教程
Visitor tweets about how you can layout the metauniverse