OpenGL學習(五) 著色器渲染(以Android為例)

來源:互聯網
上載者:User

標籤:oid   sep   config   模式   client   roi   share   const   雙緩衝   

一、Android平台上下文環境的建立及初始化

1. 首先執行個體化Android上下文環境,即EGL的初始化。

bool EGLCore::init(EGLContext sharedContext) {    EGLint numConfigs;    EGLint width;    EGLint height;    const EGLint attribs[] = { EGL_BUFFER_SIZE, 32, EGL_ALPHA_SIZE, 8, EGL_BLUE_SIZE, 8, EGL_GREEN_SIZE, 8, EGL_RED_SIZE, 8, EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,    EGL_SURFACE_TYPE, EGL_WINDOW_BIT, EGL_NONE };    //eglGetDisplay來返回OpenGL ES渲染的目標,每個廠商都會返回預設的顯示裝置    if ((display = eglGetDisplay(EGL_DEFAULT_DISPLAY)) == EGL_NO_DISPLAY) {        LOGE("eglGetDisplay() returned error %d", eglGetError());        return false;    }    // 初始化顯示裝置    if (!eglInitialize(display, 0, 0)) {        LOGE("eglInitialize() returned error %d", eglGetError());        return false;    }    // 得到配置選項資訊    if (!eglChooseConfig(display, attribs, &config, 1, &numConfigs)) {        LOGE("eglChooseConfig() returned error %d", eglGetError());        release();        return false;    }    // 建立OpenGL的上下文環境EGLContext    EGLint eglContextAttributes[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };    if (!(context = eglCreateContext(display, config, NULL == sharedContext ? EGL_NO_CONTEXT : sharedContext, eglContextAttributes))) {        LOGE("eglCreateContext() returned error %d", eglGetError());        release();        return false;    }    pfneglPresentationTimeANDROID = (PFNEGLPRESENTATIONTIMEANDROIDPROC)eglGetProcAddress("eglPresentationTimeANDROID");    if (!pfneglPresentationTimeANDROID) {        LOGE("eglPresentationTimeANDROID is not available!");    }    return true;}

2. 將EGL和裝置的螢幕串連起來。使用EGLSurface,通過EGL庫提供的eglCreateWindowSurface可以建立一個可實際顯示的Surface,通過EGL庫提供的eglCreatePbufferSurface可以建立一個OffScreen的Surface。_window就是通過Java層的Surface對象建立出的ANativeWindow類型的對象,即本地裝置螢幕的表示。也就是說真實顯示的Surface還是通過Java層建立好的, 然後OpenGL只是繪製到了這個target上邊?

EGLSurface EGLCore::createWindowSurface(ANativeWindow* _window) {    EGLSurface surface = NULL;    EGLint format;    if (!eglGetConfigAttrib(display, config, EGL_NATIVE_VISUAL_ID, &format)) {        LOGE("eglGetConfigAttrib() returned error %d", eglGetError());        release();        return surface;    }    ANativeWindow_setBuffersGeometry(_window, 0, 0, format);    if (!(surface = eglCreateWindowSurface(display, config, _window, 0))) {        LOGE("eglCreateWindowSurface() returned error %d", eglGetError());    }    return surface;}

通過Java層的Surface對象建立ANativeWindow類型的對象方法如下:

JNIEXPORT void JNICALL Java_com_phuket_tour_opengl_renderer_PngPreviewController_setSurface(JNIEnv * env, jobject obj, jobject surface) {    if (surface != 0 && NULL != controller) {        window = ANativeWindow_fromSurface(env, surface);        LOGI("Got window %p", window);        controller->setWindow(window);    } else if (window != 0) {        LOGI("Releasing window");        ANativeWindow_release(window);        window = 0;    }}

3. 開發人員需要開闢一個新的縣城,來執行OpenGL ES的渲染操作,而且還必須為該縣城綁定顯示裝置(surface)與上下文環境(Context)。EGL是雙緩衝模式,內部有兩個FrameBuffer,當EGL將一個FrameBuffer顯示到螢幕上的時候,另外一個FrameBuffer就在後台等待OpenGL ES進行渲染輸出了。直到調用函數eglSwapBuffers這條指令的時候,才會把前台的FrameBuffer和背景FrameBuffer進行交換。

bool EGLCore::makeCurrent(EGLSurface eglSurface) {    return eglMakeCurrent(display, eglSurface, eglSurface, context);}
二、Texture/Shader/Program

 1. 建立Texture(紋理)

int PicPreviewTexture::initTexture() {    glGenTextures(1, &texture);    glBindTexture(GL_TEXTURE_2D, texture);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);    return 1;}

2. 建立/初始化/編譯Shader

GLuint PicPreviewRender::compileShader(GLenum type, const char *sources) {    GLint status;    GLuint shader = glCreateShader(type);    if (shader == 0 || shader == GL_INVALID_ENUM) {        LOGI("Failed to create shader %d", type);        return 0;    }    glShaderSource(shader, 1, &sources, NULL);    glCompileShader(shader);    glGetShaderiv(shader, GL_COMPILE_STATUS, &status);    if (status == GL_FALSE) {        glDeleteShader(shader);        LOGI("Failed to compile shader : %s\n", sources);        return 0;    }    return shader;}

3. 建立並使用Program

int PicPreviewRender::useProgram() {    program = glCreateProgram();    glAttachShader(program, vertShader);    glAttachShader(program, fragShader);    glBindAttribLocation(program, ATTRIBUTE_VERTEX, "position");    glBindAttribLocation(program, ATTRIBUTE_TEXCOORD, "texcoord");    glLinkProgram(program);    GLint status;    glGetProgramiv(program, GL_LINK_STATUS, &status);    if (status == GL_FALSE) {        LOGI("Failed to link program %d", program);        return -1;    }    glUseProgram(program);    uniformSampler = glGetUniformLocation(program, "yuvTexSampler");    return 1;}
 三、渲染操作
void PicPreviewRender::render(){    glViewport(_backingLeft, _backingTop, _backingWidth, _backingHeight);    glClearColor(0.0f, 0.0f, 1.0f, 0.0f);    glClear(GL_COLOR_BUFFER_BIT);    glEnable(GL_BLEND);    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);    glUseProgram(program);    static const GLfloat _vertices[] = { -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, -1.0f };    glVertexAttribPointer(ATTRIBUTE_VERTEX, 2, GL_FLOAT, 0, 0, _vertices);    glEnableVertexAttribArray(ATTRIBUTE_VERTEX);    static const GLfloat texCoords[] = { 0.0f, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f, 1.0f };    glVertexAttribPointer(ATTRIBUTE_TEXCOORD, 2, GL_FLOAT, 0, 0, texCoords);    glEnableVertexAttribArray(ATTRIBUTE_TEXCOORD);    picPreviewTexture->bindTexture(uniformSampler);    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);}

執行完渲染操作後,調用eglSwapBuffers即可顯示。至此,一次渲染操作完成。

OpenGL學習(五) 著色器渲染(以Android為例)

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.