GLES3使用GPGPU记录

编译

ndk-build
adb push  ../libs/armeabi-v7a/libopengles_module /data/local/tmp/ && adb push shaders.h /data/local/tmp/testVertex.vert

adb shell

LD_LIBRARY_PATH=. ./libopengles_module  && cp targetImage960.yuv /sdcard/

显示结果

adb pull /sdcard/targetImage960.yuv .
ipython tesyuv2.py targetImage960.yuv 1920 960 NV21

一些资料

替换纹理

android - Why OpenGL ES functions cannot be called from another thread - Stack Overflow

#es2.0与es3.0版本差异:
~~GLSL:
类型声明 attribute varying —>in out~~

non-nomalized texture

Rectangle Texture - OpenGL.org

Is it possible to use unnormalized texture coordinates from a GLES2 GLSL fragment shader? - Game Development Stack Exchange

Sampler (GLSL) - OpenGL.org

opengl es 2.0 - Is rectangle texture supported by GLES 2.0 - Stack Overflow
Is it possible to get texture Integer Coordinate?

Image Load Store - OpenGL.org
但是GLES没有image2D.
GLES去除了整型索引纹理的特性,可能原本整型索引就是浮点型纹理坐标索引的封装,效率不高.所以在我们的程序中也放弃使用了.

关于glTexImage2D函数和它的参数

glTexImage2D - OpenGL ES 3 Reference Pages

glTexImage2D

纹理是GPGPU计算中重要数据输入.虽然感觉有点奇怪,但是GLSL做大数据输入并行计算确实只能这么做.另一种小量数据可以用uniform type 数组,然后一个个uniform变量设置.但是uniform数组有限制大小.不能大量输入.所以只能把无序数据封装成纹理.在glsl中定位纹理坐标使用.以输入YUV411(NV21)数据为例:
Y分量:

    glBindTexture ( GL_TEXTURE_2D, texture );
    glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE, w, h, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, buffer); buffer);
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_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 );
    glBindTexture(GL_TEXTURE_2D, 0);  

注意glTexImage2D函数.Internal Format Format Type参数要一一对应.参考上面链接的表1和表2.在我的测试中用表2的有些参数数据出不来,例如GL_RG8UI/GL_RG_INTEGER/GL_UNSIGNED_BYTE应该输出像素的整型格式数据(0~255),结果映射回来全为0.所以,尽量用表1吧.那么UV数据这样表示:

glTexImage2D ( GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w, h, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, buffer);

当需要3分量时用GL_RGB,需要4分量时用GL_RGBA.
glsl中取出数据:

        vec2 y_coord =  ;//设置纹理坐标
        yuv.x = texture(Sampler_A_Y, y_coord).x;
        yuv.y = texture(Sampler_A_UV,y_coord).r;
        yuv.z = texture(Sampler_A_UV,y_coord).w;

GL_LUMINANCE_ALPHA 对应的是rw分量.GL_LUMINANCE对应x分量.其它分量为0或1填充.

顶点反馈

refer to:
Exploring GPGPU on iOS - Bartosz Ciechanowski
以往把计算数据取出来的做法是在片段着色器中填充结果纹理,然后readPixel读出来.但是ES3有个新特性-顶点反馈能方便GPGPU计算把结果读出来.
步骤:
1. 在glsl中把要反馈的变量声明为out修饰:

flat out uint ty;               
flat out uint tuv;
  1. 编译shader后,调用glTransformFeedbackVaryings设置反馈变量,再链接一次.
    glLinkProgram(program);
    checkGlError("link");
    const char * varyings[] = {"ty","tuv"}; //NOTE! 这些变量必须在shader中有赋值.
    glTransformFeedbackVaryings(program, sizeof(varyings)/sizeof(*varyings), varyings, GL_INTERLEAVED_ATTRIBS);// size = 3 * 4 / 4
    for (GLint error = glGetError(); error; error = glGetError()) {
        printf("after () glError (0x%x)\n", error);
    }
    //relink!
    glLinkProgram(program);
  1. 分配一个输出VBO:
    glBindBuffer(GL_ARRAY_BUFFER,dstVBO);
    glBufferData(GL_ARRAY_BUFFER, sizeof ( YUV_t ) * I_TARGET_SIZE, destBuffer, GL_DYNAMIC_COPY);  
  1. draw输出到缓冲区
    在帧更新函数加入:
    glBindBuffer ( GL_TRANSFORM_FEEDBACK_BUFFER, dstVBO );
        checkGlError("calculateByGPU:glBindBuffer");
    glBindBufferBase ( GL_TRANSFORM_FEEDBACK_BUFFER, 0, dstVBO );
        checkGlError("calculateByGPU:glBindBufferBase");
    glBeginTransformFeedback ( GL_POINTS );
    glDrawArrays ( GL_POINTS, 0, I_TARGET_SIZE );
    glEndTransformFeedback();   
  1. 最后把VBO映射回内存:
    glBindBuffer(GL_ARRAY_BUFFER, dstVBO);
    YUV_t *memoryBuffer = (YUV_t *)glMapBufferRange(GL_ARRAY_BUFFER, 0, sizeof(YUV_t) * I_TARGET_SIZE , GL_MAP_READ_BIT);
    glUnmapBuffer(GL_ARRAY_BUFFER);

other

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值