当前位置:网站首页>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
边栏推荐
- 简单描述 MySQL 中,索引,主键,唯一索引,联合索引 的区别,对数据库的性能有什么影响(从读写两方面)
- 接口自动化测试实践指导(上):接口自动化需要做哪些准备工作
- AttributeError: Can‘t get attribute ‘SPPF‘ on <module ‘models. common‘ from ‘/home/yolov5/models/comm
- 巴比特 | 元宇宙每日必读:中国互联网企业涌入元宇宙的群像:“只有各种求生欲,没有前瞻创新的雄心”...
- NFT on fingertips | evaluate ambire on G2, and have the opportunity to obtain limited edition collections
- 【Hot100】739. 每日溫度
- RichView TRVStyle 模板样式的设置与使用
- 树莓派3B更新vim
- Cif10 actual combat (resnet18)
- The author is dead? AI is conquering mankind with art
猜你喜欢
ROS learning_ Basics
L'Ia dans les nuages rend la recherche géoscientifique plus facile
Top test sharing: if you want to change careers, you must consider these issues clearly!
WPF之MVVM
Oracle数据库11gr2使用tde透明数据加密报错ora28353,如果运行关闭wallet会报错ora28365,运行打开wallet就报错ora28353无法打开wallet
leetcode704. 二分查找(查找某个元素,简单,不同写法)
Supporting title of the book from 0 to 1: ctfer's growth road (Zhou Geng)
基于PyTorch和Fast RCNN快速实现目标识别
指尖上的 NFT|在 G2 上评价 Ambire,有机会获得限量版收藏品
Misc of BUU (update from time to time)
随机推荐
C language_ Double create, pre insert, post insert, traverse, delete
接口自动化测试实践指导(上):接口自动化需要做哪些准备工作
Depth residual network
What is the difference between int (1) and int (10)? Senior developers can't tell!
Short video, more and more boring?
Cif10 actual combat (resnet18)
After working for 10 years, I changed to a programmer. Now I'm 35 + years old and I'm not anxious
What is the biggest problem that fresh e-commerce is difficult to do now
树莓派串口登录与SSH登录方法
AttributeError: Can‘t get attribute ‘SPPF‘ on <module ‘models.common‘ from ‘/home/yolov5/models/comm
Attributeerror: can 't get attribute' sppf 'on < module' models. Common 'from' / home / yolov5 / Models / comm
Upgraded wechat tool applet source code for mobile phone detection - supports a variety of main traffic modes
When my colleague went to the bathroom, I helped my product sister easily complete the BI data product and got a milk tea reward
LeetCode 78:子集
3. Business and load balancing of high architecture
Entity Developer数据库应用程序的开发
BIO模型实现多人聊天
AI on the cloud makes earth science research easier
A brief introduction of reverseme in misc in the world of attack and defense
[server data recovery] case of offline data recovery of two hard disks of IBM server RAID5