四邊形的繪制在Opengl ES是很重要的一項技巧,比如做視頻播放器時視頻的渲染就需要使用到Opengl ES繪制四邊形的相關(guān)知識伪货。然而在Opengl ES卻沒有直接提供
繪制四邊形的相關(guān)函數(shù),那么如何實現(xiàn)四邊形的繪制呢戴差?
在Opengl ES的世界中所有的元素都是由點硕舆、線和三角形組成的。眾所周知萤衰,四邊形可以拆分成兩個三角形,因此四邊形的繪制在Opengl ES的世界中可以分解成繪制兩個三角形的任務(wù)猜旬。
關(guān)于三角形的繪制請參考之前的文章:OpenglEs之三角形繪制
代碼準(zhǔn)備
為了使得項目代碼更好地展現(xiàn)我們的demo效果脆栋,我們先來將之前的代碼抽象起來倦卖,做了個簡單的封裝,統(tǒng)一一個BaseGlActivity:
public class BaseGlActivity extends AppCompatActivity {
protected BaseOpengl baseOpengl;
private MyGLSurfaceView myGLSurfaceView;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_base_gl);
baseOpengl = createOpengl();
myGLSurfaceView = findViewById(R.id.my_gl_surface_view);
if(null != baseOpengl){
myGLSurfaceView.setBaseOpengl(baseOpengl);
myGLSurfaceView.setOnDrawListener(new MyGLSurfaceView.OnDrawListener() {
@Override
public void onDrawFrame() {
baseOpengl.onGlDraw();
}
});
}
}
@Override
protected void onDestroy() {
if(null != baseOpengl){
baseOpengl.release();
}
super.onDestroy();
}
// 子類返回具體的Opelg實體即可
public BaseOpengl createOpengl() {
return null;
}
}
其他代碼椿争,例如BaseOpengl和MyGLSurfaceView和以前的一樣怕膛。
然后在Java層和C++都新建一個RectOpengl類,用來表示繪制四邊形秦踪。
RectOpengl.java
public class RectOpengl extends BaseOpengl{
public RectOpengl() {
super(BaseOpengl.DRAW_TYPE_RECT);
}
}
RectOpengl.h
#ifndef NDK_OPENGLES_LEARN_RECTOPENGL_H
#define NDK_OPENGLES_LEARN_RECTOPENGL_H
#include "BaseOpengl.h"
class RectOpengl:public BaseOpengl {
public:
RectOpengl();
virtual ~RectOpengl();
virtual void onDraw();
private:
GLint positionHandle{-1};
GLint colorHandle{-1};
};
#endif //NDK_OPENGLES_LEARN_RECTOPENGL_H
六點頂點繪制四邊形
這是所有人都能想到的最簡單的方式了褐捻,每個三角形需要三個頂點,繪制兩個三角形則需要六個頂點椅邓,通過調(diào)整頂點柠逞,將兩個三角形緊挨著就組成了四邊形。
因此景馁,我們的頂點著色器和片段著色器都不需要修改板壮,直接使用之前繪制三角形的那些著色器即可。
例如使用下面六個頂點繪制兩個三角形:
// 使用繪制兩個三角形組成一個矩形的形式 GL_TRIANGLES
//const static GLfloat VERTICES[] = {
// // 第一個三角形
// 0.5f,0.5f,
// -0.5f,0.5f,
// -0.5f,-0.5f,
// // 第二個三角形
// -0.5f,-0.5f,
// 0.5f,-0.5f,
// 0.5f,0.5f
//};
// 6個頂點繪制兩個三角形組成矩形 GL_TRIANGLES
// glDrawArrays(GL_TRIANGLES,0,6);
這個理解起來比較簡單合住,筆者就不畫說明圖了绰精。
四個頂點繪制四邊形
使用四個頂點繪制兩個三角形主要是復(fù)用了部分頂點,然后在glDrawArrays
函數(shù)中使用繪制三角形帶的方式進行繪制透葛。
// 4個頂點繪制兩個三角形組成矩形
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
GL_TRIANGLE_STRIP會復(fù)用前面的頂點笨使,因為頂點復(fù)用,因此這種方式可以繪制出n-2
個三角形(n是頂點的個數(shù))获洲。
例如使用三角形帶的方式搭配以下的頂點坐標(biāo)即可繪制出一個矩形:
const static GLfloat VERTICES[] = {
0.5f,-0.5f, // 右下
0.5f,0.5f, // 右上
-0.5f,-0.5f, // 左下
-0.5f,0.5f // 左上
};
假如有1阱表、2、3贡珊、4這四個頂點坐標(biāo)最爬,那么GL_TRIANGLE_STRIP繪制三角形的的方式是頂點1、2门岔、3組成一個三角形爱致,頂點2、3寒随、4組成一個三角形糠悯。
具體看圖:
[圖片上傳失敗...(image-9e857-1663898911617)]
RectOpengl完整代碼:
#include "RectOpengl.h"
#include "../utils/Log.h"
// 頂點著色器
static const char *ver = "#version 300 es\n"
"in vec4 aColor;\n"
"in vec4 aPosition;\n"
"out vec4 vColor;\n"
"void main() {\n"
" vColor = aColor;\n"
" gl_Position = aPosition;\n"
"}";
// 片元著色器
static const char *fragment = "#version 300 es\n"
"precision mediump float;\n"
"in vec4 vColor;\n"
"out vec4 fragColor;\n"
"void main() {\n"
" fragColor = vColor;\n"
"}";
// 使用繪制兩個三角形組成一個矩形的形式 GL_TRIANGLES
//const static GLfloat VERTICES[] = {
// // 第一個三角形
// 0.5f,0.5f,
// -0.5f,0.5f,
// -0.5f,-0.5f,
// // 第二個三角形
// -0.5f,-0.5f,
// 0.5f,-0.5f,
// 0.5f,0.5f
//};
// 使用繪制兩個三角形組成一個矩形的形式(三角形帶)
// 第一第二第三個點組成一個三角形,第二第三第四個點組成一個三角形
const static GLfloat VERTICES[] = {
0.5f,-0.5f, // 右下
0.5f,0.5f, // 右上
-0.5f,-0.5f, // 左下
-0.5f,0.5f // 左上
};
// rgba
const static GLfloat COLOR_ICES[] = {
0.0f,0.0f,1.0f,1.0f
};
RectOpengl::RectOpengl():BaseOpengl() {
initGlProgram(ver,fragment);
positionHandle = glGetAttribLocation(program,"aPosition");
colorHandle = glGetAttribLocation(program,"aColor");
LOGD("program:%d",program);
LOGD("positionHandle:%d",positionHandle);
LOGD("colorHandle:%d",colorHandle);
}
void RectOpengl::onDraw() {
// 清屏
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
/**
* size 幾個數(shù)字表示一個點妻往,顯示是兩個數(shù)字表示一個點
* normalized 是否需要歸一化互艾,不用,這里已經(jīng)歸一化了
* stride 步長讯泣,連續(xù)頂點之間的間隔纫普,如果頂點直接是連續(xù)的,也可填0
*/
glVertexAttribPointer(positionHandle,2,GL_FLOAT,GL_FALSE,0,VERTICES);
// 啟用頂點數(shù)據(jù)
glEnableVertexAttribArray(positionHandle);
// 這個不需要glEnableVertexAttribArray
glVertexAttrib4fv(colorHandle, COLOR_ICES);
// 6個頂點繪制兩個三角形組成矩形
// glDrawArrays(GL_TRIANGLES,0,6);
// 4個頂點繪制兩個三角形組成矩形
glDrawArrays(GL_TRIANGLE_STRIP,0,4);
glUseProgram(0);
// 禁用頂點
glDisableVertexAttribArray(positionHandle);
if(nullptr != eglHelper){
eglHelper->swapBuffers();
}
}
RectOpengl::~RectOpengl() noexcept {
}
DrawRectActivity.java
public class DrawRectActivity extends BaseGlActivity{
@Override
public BaseOpengl createOpengl() {
return new RectOpengl();
}
}
[圖片上傳失敗...(image-9e4b53-1663898911617)]
往期筆記
Opengl ES之EGL環(huán)境搭建
Opengl ES之著色器
Opengl ES之三角形繪制
關(guān)注我好渠,一起進步昨稼,人生不止coding=谑印!假栓!