美文网首页后端砖头
OpenGL系列之二十一:投影变换

OpenGL系列之二十一:投影变换

作者: itfitness | 来源:发表于2023-02-06 21:06 被阅读0次

目录

相关文章

OpenGL系列之一:OpenGL第一个程序
OpenGL系列之二:绘制三角形
OpenGL系列之三:三角形顶点增加颜色
OpenGL系列之四:绘制四边形
OpenGL系列之五:绘制点和线
OpenGL系列之六:绘制立方体
OpenGL系列之七:纹理贴图
OpenGL系列之八:立方体纹理贴图
OpenGL系列之九:glsl着色器语言
OpenGL系列之十:VAO、VBO、EBO的应用
OpenGL系列之十一:Shader图片转场切换动画
OpenGL系列之十二:Shader燃烧动画
OpenGL系列之十三:实现Shader绚丽动画
OpenGL系列之十四:实现相机抖音特效
OpenGL系列之十五:实现美颜相机
OpenGL系列之十六:实现大眼特效
OpenGL系列之十七:实现人脸贴纸
OpenGL系列之十八:FBO离屏渲染
OpenGL系列之十九:OpenGL人脸贴纸
OpenGL系列之二十:EGL

参考文章

https://blog.csdn.net/Kennethdroid/article/details/100898155
https://blog.csdn.net/wangdingqiaoit/article/details/51594408

投影变换

OpenGL中的投影方式主要有两种,即透视投影(perspective projection)和正交投影(orthographic projection)。
透视投影:简单讲就像我们用自己的眼睛看东西,距离近看着比较大,距离远看着比较小
正交投影:与透视投影不同的是不管多远的距离成像大小都一样


在OpenGL中我们借助glm(这篇文章中介绍了glm的引入:OpenGL系列之六:绘制立方体
)实现透视投影正交投影
透视投影

第一个参数是视野,一般为45,第二个参数为屏幕宽高比,第三个参数为近平面(最近可观察的距离),第四个参数为远平面(最远观察的距离)

glm::mat4 Projection = glm::perspective(45.0f,ratio, 0.1f,100.f);

另外我们还需要一个观察矩阵

// View matrix
 glm::mat4 View = glm::lookAt(
            glm::vec3(0, 0, 4), // Camera is at (0,0,1), in World Space
            glm::vec3(0, 0, 0), // and looks at the origin
            glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down)
);

然后我们就可以利用模型矩阵进行旋转、平移、缩放等的变换,另外之所以glm::translate中z轴的移动使用了宽高比,那是因为经过我的测试,刚好设置为这个值,可以让渲染的图像左右与屏幕贴合,另外如果想要渲染的图像与整个屏幕缩放贴合的话需要将顶点坐标的y轴的值设置为高与宽的比(ps:透视投影是这种情况)

    glm::mat4 Model = glm::mat4(1.0f);
    Model = glm::translate(Model, glm::vec3(0.0f, 0.0f, ratio));
    Model = glm::scale(Model, glm::vec3(1.0f, 1.0f, 1.0f));
    Model = glm::rotate(Model, radiansX, glm::vec3(1.0f, 0.0f, 0.0f));
    Model = glm::rotate(Model, radiansY, glm::vec3(0.0f, 1.0f, 0.0f));

    mvpMatrix = Projection * View * Model;

然后在Activity中我们通过对手势滑动的值来算出旋转的角度,传给模型矩阵

class MainActivity : AppCompatActivity() {
    private var downX = 0.0f
    private var downY = 0.0f
    override fun onCreate(savedInstanceState: Bundle?) {

        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val path = File(getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),"aa.png")
        ResourceUtils.copyFileFromAssets("aa.png",path.absolutePath)
        Log.e("测试",path.absolutePath)
        val surfaceView = findViewById<MyGLSurfaceView>(R.id.surfaceview)
        surfaceView.setOnTouchListener { v, event ->
            when(event.action){
                MotionEvent.ACTION_DOWN->{
                    downX = event.x
                    downY = event.y
                    setAngle(0f,0f)
                }
                MotionEvent.ACTION_MOVE->{
                    val moveX = event.x - downX
                    val moveY = event.y - downY
                    Log.e("测试","${moveX}===${moveY}")
                    setAngle(moveY * 2 / surfaceView.height * 360,moveX * 2 / surfaceView.width * 360)
                }
            }
            return@setOnTouchListener true
        }
    }
    external fun setAngle(angleX:Float, angleY:Float)
}
void TextureSimple::draw() {

    // 旋转角度变换,更新变换矩阵
    UpdateMVPMatrix(m_MVPMatrix, angleX, angleY, (float)screenWidth / screenHeight);

    //绑定VAO
    vao.bind();

    //绑定Texture
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, m_texID);

    //设置Texture
    glUniform1i(m_SamplerLoc, 0);

    // 将总变换矩阵传入着色器程序
    glUniformMatrix4fv(m_MVPMatLoc, 1, GL_FALSE, &m_MVPMatrix[0][0]);

    //绘制
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, (const void *)0);

    //解绑VAO
    vao.unBind();
}
正交投影

前四个参数其实就相当于设置了渲染的X、Y轴坐标系(当然也可以自己设置自己想要的大小),即X轴-11,Y轴-11,第三第四个参数与上面的透视投影的后两个参数一样,也是近平面和远平面。

glm::mat4 Projection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, 0.1f, 100.0f);

当然也需要设置观察矩阵和模型变换矩阵

    // View matrix
    glm::mat4 View = glm::lookAt(
            glm::vec3(0, 0, 4), // Camera is at (0,0,1), in World Space
            glm::vec3(0, 0, 0), // and looks at the origin
            glm::vec3(0, 1, 0)  // Head is up (set to 0,-1,0 to look upside-down)
    );

    // Model matrix
    glm::mat4 Model = glm::mat4(1.0f);
    Model = glm::translate(Model, glm::vec3(0.0f, 0.0f, ratio));
    Model = glm::scale(Model, glm::vec3(1.0f, 1.0f, 1.0f));
    Model = glm::rotate(Model, radiansX, glm::vec3(1.0f, 0.0f, 0.0f));
    Model = glm::rotate(Model, radiansY, glm::vec3(0.0f, 1.0f, 0.0f));

    mvpMatrix = Projection * View * Model;

案例源码

https://gitee.com/itfitness/opengl-glm

相关文章

网友评论

    本文标题:OpenGL系列之二十一:投影变换

    本文链接:https://www.haomeiwen.com/subject/bwdtkdtx.html