国产精品免费嫩草研究院|无遮羞动漫在线观看AV|国产麻豆精品传媒AV国产在线|村在线观看|寂寞情人1正版|韩国床震韩国床震古|精品系列专区久久

OpenglEs之三角形繪制

在前面我們已經在NDK層搭建好了EGL環(huán)境,也介紹了一些著色器相關的理論知識,那么這次我們就使用已經搭配的EGL繪制一個三角形吧 。
【OpenglEs之三角形繪制】在Opengl ES的世界中,無論多復雜的形狀都是由點、線或三角形組成的 。因此三角形的繪制在Opengl ES中相當重要,猶比武林高手的內功心法...
坐標系在Opengl ES中有很多坐標系,今天我們首先了解一些標準化的設備坐標 。
標準化設備坐標(Normalized Device Coordinates, NDC),一旦你的頂點坐標已經在頂點著色器中處理過,它們就是標準化設備坐標了,標準化設備坐標是一個x、y和z的值都在-1.0到1.0的之間,任何落在-1和1范圍外的坐標都會被丟棄/裁剪,不會顯示在你的屏幕上 。
如下圖,在在標準化設備坐標中,假設有一個正方形的屏幕,那么屏幕中心就是坐標原點,左上角就是坐標(-1,1),右下角則是坐標(1,-1) 。

OpenglEs之三角形繪制

文章插圖
上代碼這里需要說明亮點:
  1. 在后續(xù)的實戰(zhàn)例子中,經常會復用到前面介紹的demo的代碼,因此如果是復用之前的代碼邏輯,為了節(jié)省篇幅,筆者就不重復貼了 。
  2. 在demo中為了簡潔,并沒有開啟子線程作為GL線程,很明顯這是不對,實際開發(fā)中都應該開啟子線程對Opengl進行操作 。
首先為了后續(xù)方便使用,我們在Java層和C++分別創(chuàng)建一個BaseOpengl的基類:
BaseOpengl.javapublic class BaseOpengl {// 三角形public static final int DRAW_TYPE_TRIANGLE = 0;public long glNativePtr;protected EGLHelper eglHelper;protected int drawType;public BaseOpengl(int drawType) {this.drawType = drawType;this.eglHelper = new EGLHelper();}public void surfaceCreated(Surface surface) {eglHelper.surfaceCreated(surface);}public void surfaceChanged(int width, int height) {eglHelper.surfaceChanged(width,height);}public void surfaceDestroyed() {eglHelper.surfaceDestroyed();}public void release(){if(glNativePtr != 0){n_free(glNativePtr,drawType);glNativePtr = 0;}}public void onGlDraw(){if(glNativePtr == 0){glNativePtr = n_gl_nativeInit(eglHelper.nativePtr,drawType);}if(glNativePtr != 0){n_onGlDraw(glNativePtr,drawType);}}// 繪制private native void n_onGlDraw(long ptr,int drawType);protected native long n_gl_nativeInit(long eglPtr,int drawType);private native void n_free(long ptr,int drawType);}下面是C++的BaseOpengl:
BaseOpengl.h#ifndef NDK_OPENGLES_LEARN_BASEOPENGL_H#define NDK_OPENGLES_LEARN_BASEOPENGL_H#include "../eglhelper/EglHelper.h"#include "GLES3/gl3.h"#include <string>class BaseOpengl {public:EglHelper *eglHelper;GLint program{0};public:BaseOpengl();// 析構函數(shù)必須是虛函數(shù)virtual ~BaseOpengl();// 加載著色器并鏈接成程序void initGlProgram(std::string ver,std::string fragment);// 繪制virtual void onDraw() = 0;};#endif //NDK_OPENGLES_LEARN_BASEOPENGL_H注意基類的析構函數(shù)一定要是虛函數(shù),為什么?如果不是虛函數(shù)的話則會導致無法完全析構,具體原因請大家面向搜索引擎編程 。
BaseOpengl.cpp#include "BaseOpengl.h"#include "../utils/ShaderUtils.h"BaseOpengl::BaseOpengl() {}void BaseOpengl::initGlProgram(std::string ver, std::string fragment) {program = createProgram(ver.c_str(),fragment.c_str());}BaseOpengl::~BaseOpengl(){eglHelper = nullptr;if(program != 0){glDeleteProgram(program);}}然后使用BaseOpengl自定義一個SurfaceView,為MyGLSurfaceView:
public class MyGLSurfaceView extends SurfaceView implements SurfaceHolder.Callback {public BaseOpengl baseOpengl;private OnDrawListener onDrawListener;public MyGLSurfaceView(Context context) {this(context,null);}public MyGLSurfaceView(Context context, AttributeSet attrs) {super(context, attrs);getHolder().addCallback(this);}public void setBaseOpengl(BaseOpengl baseOpengl) {this.baseOpengl = baseOpengl;}public void setOnDrawListener(OnDrawListener onDrawListener) {this.onDrawListener = onDrawListener;}@Overridepublic void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {if(null != baseOpengl){baseOpengl.surfaceCreated(surfaceHolder.getSurface());}}@Overridepublic void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int w, int h) {if(null != baseOpengl){baseOpengl.surfaceChanged(w,h);}if(null != onDrawListener){onDrawListener.onDrawFrame();}}@Overridepublic void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {if(null != baseOpengl){baseOpengl.surfaceDestroyed();}}public interface OnDrawListener{void onDrawFrame();}}

經驗總結擴展閱讀