Open GL의 기본적인 코드는
https://developer.android.com/develop/ui/views/graphics/opengl
위 사이트에 공개된 코드를 사용하였다.
MainActivity.java
package com.example.open_gl_primitives;
import androidx.appcompat.app.AppCompatActivity;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
private GLSurfaceView gLView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Create a GLSurfaceView instance and set it
// as the ContentView for this Activity.
gLView = new MyGLSurfaceView(this);
setContentView(gLView);
}
}
MyGLSurfaceView.java
package com.example.open_gl_primitives;
import android.content.Context;
import android.opengl.GLSurfaceView;
class MyGLSurfaceView extends GLSurfaceView {
private final MyGLRenderer renderer;
public MyGLSurfaceView(Context context){
super(context);
// Create an OpenGL ES 2.0 context
setEGLContextClientVersion(2);
renderer = new MyGLRenderer();
// Set the Renderer for drawing on the GLSurfaceView
setRenderer(renderer);
}
}
MyGLRenderer.java
package com.example.open_gl_primitives;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
public class MyGLRenderer implements GLSurfaceView.Renderer {
// vPMatrix is an abbreviation for "Model View Projection Matrix"
private final float[] vPMatrix = new float[16];
private final float[] projectionMatrix = new float[16];
private final float[] viewMatrix = new float[16];
private Primitives mPrimitives;
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
// Set the background frame color
//GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
//배경색을 하얀색을 바꿔줌
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
mPrimitives = new Primitives();
}
public void onDrawFrame(GL10 unused) {
// Redraw background color
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
// Set the camera position (View matrix)
Matrix.setLookAtM(viewMatrix, 0, 0, 0, -3, 0f, 0f, 0f, 0f, 1.0f, 0.0f);
// Calculate the projection and view transformation
Matrix.multiplyMM(vPMatrix, 0, projectionMatrix, 0, viewMatrix, 0);
mPrimitives.draw(vPMatrix);
}
public void onSurfaceChanged(GL10 unused, int width, int height) {
GLES20.glViewport(0, 0, width, height);
float ratio = (float) width / height;
// this projection matrix is applied to object coordinates
// in the onDrawFrame() method
Matrix.frustumM(projectionMatrix, 0, ratio, -ratio, -1, 1, 3, 7);
}
public static int loadShader(int type, String shaderCode){
// create a vertex shader type (GLES20.GL_VERTEX_SHADER)
// or a fragment shader type (GLES20.GL_FRAGMENT_SHADER)
int shader = GLES20.glCreateShader(type);
// add the source code to the shader and compile it
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
}
이와 같은 코드를 이용해 MyGLRenderer.java class 에서 배경색을 지정해준다.
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
//Set the background frame color 배경색을 하얀색을 바꿔줌
GLES20.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
mPrimitives = new Primitives();
}
Primitives.java
package com.example.open_gl_primitives;
import android.opengl.GLES20;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
public class Primitives {
private final String vertexShaderCode =
// This matrix member variable provides a hook to manipulate
// the coordinates of the objects that use this vertex shader
"uniform mat4 uMVPMatrix;" +
"attribute vec4 vPosition;" +
"void main() {" +
// the matrix must be included as a modifier of gl_Position
// Note that the uMVPMatrix factor *must be first* in order
// for the matrix multiplication product to be correct.
" gl_Position = uMVPMatrix * vPosition;" +
"}";
// Use to access and set the view transformation
private int vPMatrixHandle;
private FloatBuffer vertexBuffer;
private final int mProgram;
private int positionHandle;
private int colorHandle;
//private final int vertexCount = triangleCoords.length / COORDS_PER_VERTEX;
private final int vertexStride = COORDS_PER_VERTEX * 4; // 4 bytes per vertex
// number of coordinates per vertex in this array
static final int COORDS_PER_VERTEX = 3;
// static float triangleCoords[] = { // in counterclockwise order:
// -0.5f, 0.622008459f, 0.0f, // top
// -0.5f, -0.311004243f, 0.0f, // bottom left
// 0.5f, -0.311004243f, 0.0f // bottom right
// };
float Vertex_coor[] = {
// X, Y, Z
0.5f, 0.5f, 0, //v0
-0.5f, 0.5f, 0, //v1
0.0f, 0.2f, 0, //v2
-0.3f, -0.2f, 0, //v3
0.3f, -0.3f, 0, //v4
0.0f, -0.8f, 0 //v5
}; //vertex(점)을 바꿔주면 삼각형이 아닌 다른 값들을 넣어줘 다른 모양을 만들어줄 수 있음
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
//set color to black (색을 검정으로 바꿔줌)
float color_black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
public Primitives() {
// initialize vertex byte buffer for shape coordinates
ByteBuffer bb = ByteBuffer.allocateDirect(
// (number of coordinate values * 4 bytes per float)
Vertex_coor.length * 4);
// use the device hardware's native byte order
bb.order(ByteOrder.nativeOrder());
// create a floating point buffer from the ByteBuffer
vertexBuffer = bb.asFloatBuffer();
// add the coordinates to the FloatBuffer
vertexBuffer.put(Vertex_coor);
// set the buffer to read the first coordinate
vertexBuffer.position(0);
int vertexShader = MyGLRenderer.loadShader(GLES20.GL_VERTEX_SHADER,
vertexShaderCode);
int fragmentShader = MyGLRenderer.loadShader(GLES20.GL_FRAGMENT_SHADER,
fragmentShaderCode);
// create empty OpenGL ES Program
mProgram = GLES20.glCreateProgram();
// add the vertex shader to program
GLES20.glAttachShader(mProgram, vertexShader);
// add the fragment shader to program
GLES20.glAttachShader(mProgram, fragmentShader);
// creates OpenGL ES program executables
GLES20.glLinkProgram(mProgram);
}
public void draw(float[] mvpMatrix) {
// get handle to shape's transformation matrix
vPMatrixHandle = GLES20.glGetUniformLocation(mProgram, "uMVPMatrix");
// Pass the projection and view transformation to the shader
GLES20.glUniformMatrix4fv(vPMatrixHandle, 1, false, mvpMatrix, 0);
// Add program to OpenGL ES environment
GLES20.glUseProgram(mProgram);
// get handle to vertex shader's vPosition member
positionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition");
// Enable a handle to the triangle vertices
GLES20.glEnableVertexAttribArray(positionHandle);
// Prepare the vertex coordinate data
GLES20.glVertexAttribPointer(positionHandle, COORDS_PER_VERTEX,
GLES20.GL_FLOAT, false,
vertexStride, vertexBuffer);
// get handle to fragment shader's vColor member
colorHandle = GLES20.glGetUniformLocation(mProgram, "vColor");
// Set color for drawing the object
GLES20.glUniform4fv(colorHandle, 1, color_black, 0);
//Draw the object (2개의 vertex를 읽어 선을 그린다)
GLES20.glDrawArrays(GLES20.GL_LINES, 0, 2);
// Draw the object (6개의 vertex를 읽어 선을 그린다)
//GLES20.glDrawArrays(GLES20.GL_LINES, 0, 6);
// Draw the object (1번 vertex부터 읽어 4번 vertex까지 그린다)
//GLES20.glDrawArrays(GLES20.GL_LINES, 1, 4);
// Draw the object (line_strip은 0부터 3개 이어서 그려줌) 0 1 2 (총 3개)
//GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, 3);
// Draw the object (line_strip은 0부터 6개 이어서 그려줌) 0 1 2 3 4 5 (총 6개)
//GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, 6);
// Draw the object (line_strip은 1부터 3개 이어서 그려줌) 1 2 3 (총 3개)
//GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 1, 3);
// Draw the object (line_loop 0부터 6개 다 이어서 루프형식으로 그려줌, 마지막 0과 5를 합쳐줌) 0 1 2 3 4 5 (총 6개)
//GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 0, 6);
// Draw the object (line_loop 0부터 4개 다 이어서 루프형식으로 그려줌, 마지막 0과 3를 합쳐줌) 0 1 2 3 (총 4개)
//GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 0, 4);
// Draw the object(0부터 시작해서 3개의 점을 이어 안을 색칠해 준다) 0 1 2
//GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
//vertex 3개가 하나의 삼각형을 만듬 0 1 2 하나 3 4 5 하나 총 두개의 삼각형을 만들 수 있음음
//GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
//시작점도 바꿔줄 수 있음 1 2 3으로 만든 삼각형
//GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 1, 3);
//임의적으로 vertex(0,0)을 생성해 하나 더 삼각혐 만들어버림 (뭥미?!)
//GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 1, 6);
//3개 이상의 점을 이용해 삼각형의 형태를 만들고 싶을 때 사용하는 함수 / 0 1 2 하나 1 2 3 하나 두개의 삼각형이 합쳐서 보여짐
//GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
// 0 1 2 하나 1 2 3 하나 2 3 4 하나 3 4 5 하나 총 4개의 삼각형이 합쳐진 형태
//GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 6);
//1 2 3 하나 2 3 4 하나
//GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 1, 4);
//0 1 2 하나 0 2 3 하나 두개의 삼각형이 만들어짐 , 두번쨰 삼각형 제작시 0 사용
//GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
//1 2 3 하나 1 3 4 하나 두개의 삼각형이 만들어짐, 두번 쨰 삼각형 제작시 1 사용
//GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 1, 4);
// Disable vertex array
GLES20.glDisableVertexAttribArray(positionHandle);
}
private final String fragmentShaderCode =
"precision mediump float;" +
"uniform vec4 vColor;" +
"void main() {" +
" gl_FragColor = vColor;" +
"}";
}
float Vertex_coor[] = {
// X, Y, Z
0.5f, 0.5f, 0, //v0
-0.5f, 0.5f, 0, //v1
0.0f, 0.2f, 0, //v2
-0.3f, -0.2f, 0, //v3
0.3f, -0.3f, 0, //v4
0.0f, -0.8f, 0 //v5
}; //vertex(점)을 바꿔주면 삼각형이 아닌 다른 값들을 넣어줘 다른 모양을 만들어줄 수 있음
위와 같이 선을 그리게 될 점의 위치를 지정해준다.
// Set color with red, green, blue and alpha (opacity) values
float color[] = { 0.63671875f, 0.76953125f, 0.22265625f, 1.0f };
//set color to black (색을 검정으로 바꿔줌)
float color_black[] = { 0.0f, 0.0f, 0.0f, 0.0f };
아래 URL을 이용해 원하는 색의 RGB 값을 지정해준다.
colors calculator: https://www.rapidtables.com/web/color/RGB_Color.html
RGB Color Codes Chart 🎨
RGB Color Codes Chart RGB color picker | RGB color codes chart | RGB color space | RGB color format and calculation | RGB color table RGB color picker RGB color codes chart Hover with cursor on color to get the hex and decimal color codes below: RGB color
www.rapidtables.com

// Draw the object (1번 vertex부터 읽어 4번 vertex까지 그린다)
GLES20.glDrawArrays(GLES20.GL_LINES, 1, 4);
위와 같은 코드는 GL_LINES를 이용해 1번부터 4번까지 지정된 점을 이용하는데 1,2번을 이용한 직선, 3, 4번을 이용한 직선.
두개의 직선을 "따로" 그리게 된다.

// Draw the object (line_strip은 0부터 6개 이어서 그려줌) 0 1 2 3 4 5 (총 6개)
GLES20.glDrawArrays(GLES20.GL_LINE_STRIP, 0, 6);
위와 같은 코드는 GL_LINE_STRIP을 이용해 0번부터 5번까지 총 6개의 점을 이용해
"하나"의 직선을 그려준다.

//Draw the object (line_loop 0부터 6개 다 이어서 루프형식으로 그려줌, 마지막 0과 5를 합쳐줌) 0 1 2 3 4 5 (총 6개)
GLES20.glDrawArrays(GLES20.GL_LINE_LOOP, 0, 6);
위와 같은 코드는 GL_LINE_LOOP를 이용해 0 1 2 3 4 5, 6개의 점을 이어 도형을 만들어준다.
즉, 0번과 5번 점을 이어 하나의 Loop을 만든다고 생각하면 된다.

// Draw the object(0부터 시작해서 3개의 점을 이어 안을 색칠해 준다) 0 1 2
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);
위와 같은 콛드는 GL_TRIANGLES를 이용해 0, 1, 2, 3개의 점을 이어 도형을 그리고 안을 색칠해주는 코드이다.
색을 변경할 수도 있는데 이는 추후에 이용하겠다.
//vertex 3개가 하나의 삼각형을 만듬 0 1 2 하나 3 4 5 하나 총 두개의 삼각형을 만들 수 있음음
GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 6);
위와 같이 수를 설정할 경우 총 6개의 점을 이용해 2개의 삼각형을 만들 수 있다.
0 1 2 를 이용한 삼각형, 3 4 5 를 이용한 삼각형 두개의 삼각형을 그릴 수 있다.

//3개 이상의 점을 이용해 삼각형의 형태를 만들고 싶을 때 사용하는 함수 / 0 1 2 하나 1 2 3 하나 두개의 삼각형이 합쳐서 보여짐
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
위와 같은 코드는 GL_TRIANGLE_STRIP을 이용해 0 1 2 3, 총 4개의 점을 이용해 많은 삼각형을 그릴 수 있게 해주는 코드이다.
GL_TRIANGLES을 이용하면 3의 배수의 수가 있어야만 삼각형을 만들 수 있었는데 GL_TRIANGLE_STRIP 같은 경우
사용할 점의 개수를 임의로 넣어주어도 가능하다.
위와 같은 경우 총 4개의 점을 이용해 0 1 2 를 이용해 제작한 삼각형, 1 2 3 을 이용한 삼각형
총 두개의 삼각형을 그릴 수 있게된다.
// 0 1 2 하나 1 2 3 하나 2 3 4 하나 3 4 5 하나 총 4개의 삼각형이 합쳐진 형태
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 6);
이와 같이 6개의 점을 이용한 경우에도 마찬가지로
0 1 2 삼각형, 1 2 3 삼각형, 2 3 4 삼각형, 3 4 5 삼각형
총 4개의 삼각형을 그릴수 있게 된다.

//0 1 2 하나 0 2 3 하나 두개의 삼각형이 만들어짐 , 두번쨰 삼각형 제작시 0 사용
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_FAN, 0, 4);
위와 같은 코드는 GL_TRIANGLE_FAN을 이용해 삼각형을 그리게 된다.
앞에서 사용한 GL_TRIANGLE_STRIP과 차이점으로는 3개 이상의 점이 사용될 경우 마지막에 사용된 점을 이용하는 것이 아닌
제일 처음 사용한 점을 이용해 삼각형을 그린다는 것이다.
GL_TRIANGLE_STRIP의 경우 0부터 4개의 점이 있다고 가정하였을 떄,
0 1 2 / 1 2 3 두 개의 삼각형을 그리게 되지만
GL_TRIANGLE_FAN의 경우 동일하게 0부터 4개의 점이 있을 때,
0 1 2 / 0 2 3 두 개의 삼각형을 그리게 된다.
+참고자료
'실시간 운영체제' 카테고리의 다른 글
| [실시간 운영체제] Computer Graphics (Draw right angle triangle) (0) | 2023.06.14 |
|---|---|
| [실시간 운영체제] Open GL draw house (0) | 2023.06.14 |
| [실시간 운영체제] 버블정렬 (0) | 2023.05.04 |
| [실시간 운영체제] 연산 확인 작업 (pt.2) (0) | 2023.04.27 |
| [실시간 운영체제] 계산기 (0) | 2023.04.27 |