opengl基础,学习笔记

Opengl的结构和流程


glactivetexture和glbindtexture,前者用于选择一个texture unit,后者表示绑定一个texture,并且它作用于当前选择的texture unit。

可以这样简单的理解为:显卡中有N个纹理单元(具体数目依赖你的显卡能力),每个纹理单元(GL_TEXTURE0、GL_TEXTURE1等)都有GL_TEXTURE_1D、GL_TEXTURE_2D等,默认情况下当前活跃的纹理单元为0。glActiveTextue 并不是激活纹理单元,而是选择当前活跃的纹理单元。当绑定纹理目标时,所作用的是当前活跃的纹理单元。


上传cpu的memory到gpu上:

        for (int i=0; i<s->planes; i++)
        {
            GLubyte* dst;
            int k = (!!i);
            // Bind current pbo
            glBindBuffer(GL_PIXEL_UNPACK_BUFFER, s->pbo_sub[i]);
            dst = (GLubyte*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY);
            av_assert0(dst); 
            memcpy(dst, sub->data[i], sub->linesize[i]*sub->height>>k);
            glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER);

            // Select texture unit i as the active unit.
            glActiveTexture(GL_TEXTURE0+i);
            // bind the ith texture. 
            glBindTexture(GL_TEXTURE_2D, s->sub_texture[i]);
            glPixelStorei(GL_UNPACK_ALIGNMENT, 4); 
            glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, sub->height>>k); 
            glPixelStorei(GL_UNPACK_ROW_LENGTH, sub->linesize[i]); 
            glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, sub->width>>k, sub->height>>k, GL_RED, GL_UNSIGNED_BYTE, 0);
        }


Opengl里的四维变换矩阵

对三维坐标做变换时常用到四维变换矩阵,右手坐标系,对于opengl来说,可以理解坐标轴位置为,X对应左,Y对应上,Z对应前。


如图,红色是对x轴坐标的变换,绿色是对y轴,紫色是对z轴。最右面的(m12,m13,m14)是用于translation transformation, glTranslatef().
PS:glTranslatef(x,y,z)函数是沿直线移动的函数。比如glTranslatef(1,-1,2)的意思,就是沿x轴方向移动1,沿y轴方向动-1,沿z轴方向移动2。注意是相对于当前所在位置进行移动。对于全景视频我们是不需要做移动的。

最后一个m15是用于齐次坐标,投影变换的时候会用到。

变换时,opengl向量为列向量,所以应该矩阵在左边,输入向量在右边


常见几种变换矩阵,比如x轴旋转:


坐标系平移:

缩放:



Opengl里的投影变换,以及MVP

Shader

   private final String mVertexShader =
            "uniform mat4 uMVPMatrix;\n" +
                    "uniform mat4 uSTMatrix;\n" +
                    "attribute vec4 aPosition;\n" +
                    "attribute vec4 aTextureCoord;\n" +
                    "varying vec2 vTextureCoord;\n" +
                    "void main() {\n" +
                    "  gl_Position = uMVPMatrix * aPosition;\n" +
                    "  vTextureCoord = (uSTMatrix * aTextureCoord).xy;\n" +
                    "}\n";

    private final String mFragmentShader =
            "#extension GL_OES_EGL_image_external : require\n" +
                    "precision mediump float;\n" +
                    "varying vec2 vTextureCoord;\n" +
                    "uniform samplerExternalOES sTexture;\n" +
                    "void main() {\n" +
                    "  gl_FragColor = texture2D(sTexture, vTextureCoord);\n" +
                    "}\n";


对于vertex shader来说,输入参数的意义如下:

1. uSTMatrix,对输出图像坐标的变换,在全景视频播放时我们暂时不做变换,所以设置为单位矩阵即可。

2. aPosition,对应应该输入verticesBuffer,对应顶点在三维坐标系中的位置,每一个顶点由3个float值标识坐标,设置时第二个参数为3

	GLES30.glVertexAttribPointer(maPositionHandle, 3, GLES30.GL_FLOAT, false, 0, mVerticesBuffer);

3. aTextureCoord,对应输入二维图像上的点,每一个点由2个float值标识坐标,且与mVerticesBuffer中的顶点按顺序一一对应

        GLES30.glVertexAttribPointer(maTextureHandle, 2, GLES30.GL_FLOAT, false, 0, mTexCoordinateBuffer);

4. vTextureCoord,为了传给fragment shader的二维变量,由于uSTMatrix目前设置是单位矩阵,所以这里其值就是输入2D图像的坐标。


对于fragment shader,输入参数意义如下:

vTextureCoord,为了传递从vertex shader送来的2D图像坐标。

sTexture,是输入图像实际存储的texture,也就是实际数据的读取内容。它的类型samplerExternalOES将SurfaceTexture作为OpenGL外部纹理,使用GL_TEXTURE_EXTERNAL_OES作为纹理模板。对应输入的OES texture需要设置:

        mTextureID = textures[0];
        GLES30.glBindTexture(GL_TEXTURE_EXTERNAL_OES, mTextureID);

MVP矩阵

opengl在画全景图时最后会调用glDrawElements或者glDrawArrays,而投影映射的shader中一般都会有一个MVP矩阵作为输入,uMVPMatrix。这个矩阵表示了画图时的视角。它由三个矩阵按PVM的顺序相乘得到:  view矩阵 X model矩阵 X projection矩阵。

multiply(pMatrix, vMatrix, mvpMatrix); // p左乘v
multiply(mvpMatrix, mMatrix, mvpMatrix); // m左乘pv

它们的作用简单来说就是:

projection矩阵:用于最终投影出2D输出平面上的坐标

view矩阵:用于设定视角方向,也就是把world space变换到eye space

model矩阵:将物体的坐标从object space变换到画图时opengl用的3D空间,world space。如果本身输入就在opengl的空间,比如全景视频,则设置为单位矩阵即可,因为不需要这部变换。

projection矩阵

opengl在显示时,首先通在3D空间画出整个图像,对于没有特殊变换的全景视频来说就是画一个球。而显示时显示的是一个2D的图像,这时就需要投影变换,frustum。


函数原型:

    /*
     * @param m the float array that holds the output perspective matrix
     * @param offset the offset into float array m where the perspective
     *        matrix data is written
     * @param left
     * @param right
     * @param bottom
     * @param top
     * @param near
     * @param far
     */
    public static void frustumM(float[] m, int offset,
            float left, float right, float bottom, float top,
             float near, float far)

    Matrix.frustumM(mProjMatrix, 0, -ratio, ratio, -ratio, ratio, 1f, 10f);


第一个参数是输出的4x4 float 矩阵,mProjMatrix,作为投影转换矩阵。第二个参数作为偏移一般情况为0,也可以根据矩阵内存调整。第3~6个参数用于调整观测近平面的左右上下边缘,第五个参数near表示近面到视角的距离,最后一个参数表示远面到视角的距离。近面与远面投影直观理解见上面两图,小于近面或者大于远面的部分是不会投影出来的。

view矩阵

view矩阵相当于在3D空间中放置一个照相机,摆在某个位置,并且调整相机方向对准某个向量。需要调用的函数原型为:

    /**
     * Defines a viewing transformation in terms of an eye point, a center of
     * view, and an up vector.
     *
     * @param rm returns the result
     * @param rmOffset index into rm where the result matrix starts
     * @param eyeX eye point X
     * @param eyeY eye point Y
     * @param eyeZ eye point Z
     * @param centerX center of view X
     * @param centerY center of view Y
     * @param centerZ center of view Z
     * @param upX up vector X
     * @param upY up vector Y
     * @param upZ up vector Z
     */
    public static void setLookAtM(float[] rm, int rmOffset,
            float eyeX, float eyeY, float eyeZ,
            float centerX, float centerY, float centerZ, float upX, float upY,
            float upZ)
    //demo, default lookX=0, lookY=0, lookZ=-1
    Matrix.setLookAtM(mVMatrix, 0, 
                                0f, 0f, 0f, 
                                lookX, lookY, lookZ, 
                                0f, 1f, 0.0f);
输出矩阵为mVMatrix,同样是一个4x4 float矩阵。rmOffset参数是写入矩阵偏移,一般单独分给view矩阵的话设置0。eyeX,Y,Z分别表示照相机放在三维坐标中哪个点,对于全景视频来说就是原点(0,0,0)。centerX,Y,Z表示相机的朝向,它们和eye之间的向量就是相机角度,demo里输入朝向z轴负方向。最后三个参数upX,Y,Z表示相机自己头朝哪个方向,demo里设置相机房子XZ平面上,相机顶端正对着Y轴正方向。

model矩阵

对于全景视频来说,是直接贴在opengl的三维空间上的球,所以不需要进行object space到world space的转换,这个矩阵直接设置为单位矩阵就可以了。

Matrix.setIdentityM(mMMatrix, 0);

设置MVP给shader

在画图前,只需要按PVM的顺序相乘得到MVP矩阵,然后传递给shader,即可调用draw来画图了。

当然,别忘了先把vertex,coords还有indices算好传给shader。

        muMVPMatrixHandle = GLES30.glGetUniformLocation(mProgram, "uMVPMatrix");
        Matrix.multiplyMM(mMVPMatrix, 0, mVMatrix, 0, mMMatrix, 0);
        Matrix.multiplyMM(mMVPMatrix, 0, mProjMatrix, 0, mMVPMatrix, 0);
        GLES30.glUniformMatrix4fv(muMVPMatrixHandle, 1, false, mMVPMatrix, 0);

        indexBuffer.position(0);
        GLES30.glDrawElements(GLES30.GL_TRIANGLES, mNumIndices, GLES30.GL_UNSIGNED_SHORT, indexBuffer);

参考

http://www.songho.ca/opengl/gl_transform.html#modelview

http://www.songho.ca/opengl/gl_projectionmatrix.html


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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值