首页 > 其他分享 >OpenGL ES使用正交投影来解决图像变形的问题

OpenGL ES使用正交投影来解决图像变形的问题

时间:2024-09-09 16:46:19浏览次数:1  
标签:正交投影 1.0 OpenGL ES 1f var aspectRatio GL GLES30

一、概述

  上一节实践了,通过改变GLSurfaceView的宽高来解决图像变形的问题

  本节将通过正交投影的方式解决图像变形的问题。

  分三步:

    1.计算屏幕的宽高比及图像的宽高比

     var screenRatio = screenWidth.toFloat() / screenHeight
        var imgRatio = imageWidth.toFloat() / imageHeight

    2.比较屏幕宽高比及图像宽高比,并设置正交投影矩阵的参数(left、right、top、bottom、near、far)

 if (imgRatio > screenRatio) {
            var aspectRatio = imgRatio / screenRatio//计算出变换矩阵底和高
            Matrix.orthoM(
                projectionMatrix,
                0,
                -1f,
                1f,
                -aspectRatio,
                aspectRatio,
                -1f,
                1f
            )
        } else {
            var aspectRatio = screenRatio / imgRatio//计算出变换矩阵的左右
            Matrix.orthoM(
                projectionMatrix,
                0,
                -aspectRatio,
                aspectRatio,
                -1f,
                1f,
                -1f,
                1f
            )
        }

    3.将投影矩阵应用到顶点着色器的顶点上。    

 var uOrthoMLocation = GLES30.glGetUniformLocation(programId, "uOrthM")
 GLES30.glUniformMatrix4fv(uOrthoMLocation, 1, false, projectionMatrix, 0)

    4.顶点着色器字符串写法

attribute vec3 vPosition;
attribute vec2 vCoord;
varying vec2 aCoord;
uniform mat4 uOrthM;
void main(){
    gl_Position = uOrthM*vec4(vPosition,1.0f);//利用正交投影矩阵改变图片变形问题
    aCoord = vCoord;
}

 

二、完整代码如下

  1.计算投影矩阵

fun getProjectionMatrix(
        screenWidth: Int,
        screenHeight: Int,
        imageWidth: Int,
        imageHeight: Int
    ): FloatArray {
        var projectionMatrix = FloatArray(4 * 4)
        Matrix.setIdentityM(projectionMatrix, 0)//设置成单位矩阵
        var screenRatio = screenWidth.toFloat() / screenHeight
        var imgRatio = imageWidth.toFloat() / imageHeight
        if (imgRatio > screenRatio) {
            var aspectRatio = imgRatio / screenRatio//计算出变换矩阵底和高
            Matrix.orthoM(
                projectionMatrix,
                0,
                -1f,
                1f,
                -aspectRatio,
                aspectRatio,
                -1f,
                1f
            )
        } else {
            var aspectRatio = screenRatio / imgRatio//计算出变换矩阵的左右
            Matrix.orthoM(
                projectionMatrix,
                0,
                -aspectRatio,
                aspectRatio,
                -1f,
                1f,
                -1f,
                1f
            )
        }
        return projectionMatrix
    }

  2.应用投影矩阵的shader

package com.yw.filter.shader

import android.content.Context
import android.graphics.Bitmap
import android.opengl.GLES30
import android.opengl.Matrix
import com.yw.filter.R
import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.FloatBuffer
import java.nio.IntBuffer

/**
 * 利用正交投影结局图片变形问题
 */
class OrthoMTextureShader(var context: Context, var bitmapSrc: Bitmap) : BaseShader() {
    private var vertices = floatArrayOf(//在android上纹理坐标需要上下颠倒之后才能够正确显示,否则会出现镜像、颠倒等问题
        //     ---- 位置 ----    - 纹理坐标 -
        1.0f, 1.0f, 0.0f, 1.0f, 0.0f,   // 右上
        1.0f, -1.0f, 0.0f, 1.0f, 1.0f,   // 右下
        -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,   // 左下
        -1.0f, 1.0f, 0.0f, 0.0f, 0.0f    // 左上
    )
    private var indices = intArrayOf(
        0, 1, 3,//第一个三角形
        1, 2, 3 // 第二个三角形
    )
    private var vertexBuffer: FloatBuffer? = null
    private var indicesBuffer: IntBuffer? = null
    private var projectionMatrix = FloatArray(4 * 4)//正交投影矩阵
    private var VAO = IntArray(1)
    var textureId: Int = 0
    override fun onSurfaceCreate() {
        //分配空间填充数据
        vertexBuffer = ByteBuffer
            .allocateDirect(vertices.size * 4)
            .order(ByteOrder.nativeOrder())
            .asFloatBuffer()
        vertexBuffer?.put(vertices)
        vertexBuffer?.position(0)
        indicesBuffer = ByteBuffer
            .allocateDirect(indices.size * 4)
            .order(ByteOrder.nativeOrder())
            .asIntBuffer()
        indicesBuffer?.put(indices)
        indicesBuffer?.position(0)

        //创建并绑定VAO
        GLES30.glGenVertexArrays(1, VAO, 0)
        GLES30.glBindVertexArray(VAO[0])
        //创建并绑定VBO
        var VBO = IntArray(1)
        GLES30.glGenBuffers(1, VBO, 0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, VBO[0])
        GLES30.glBufferData(
            GLES30.GL_ARRAY_BUFFER,
            vertices.size * 4,
            vertexBuffer,
            GLES30.GL_STATIC_DRAW
        )

        //创建EBO
        var EBO = IntArray(1)
        GLES30.glGenBuffers(1, EBO, 0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, EBO[0])
        GLES30.glBufferData(
            GLES30.GL_ELEMENT_ARRAY_BUFFER,
            indices.size * 4,
            indicesBuffer,
            GLES30.GL_STATIC_DRAW
        )

        //告知显卡如何解析顶点数据
        GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 4 * 5, 0)
        GLES30.glEnableVertexAttribArray(0)
        //告知显卡如何解析纹理数据
        GLES30.glVertexAttribPointer(1, 2, GLES30.GL_FLOAT, false, 4 * 5, 4 * 3)
        GLES30.glEnableVertexAttribArray(1)

        //销毁
        GLES30.glBindVertexArray(0)
        GLES30.glBindBuffer(GLES30.GL_ELEMENT_ARRAY_BUFFER, 0)
        GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, 0)

        textureId = getTextureId(bitmapSrc, GLES30.GL_RGBA)

        loadProgram(context, R.raw.image_ortho_vert, R.raw.image_ortho_frag)
    }

    override fun onDrawFrame() {
        GLES30.glClearColor(1.0f, 0.0f, 0.0f, 1.0f)
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        GLES30.glBindVertexArray(VAO[0])
        GLES30.glUseProgram(programId)
        var uOrthoMLocation = GLES30.glGetUniformLocation(programId, "uOrthM")
        GLES30.glUniformMatrix4fv(uOrthoMLocation, 1, false, projectionMatrix, 0)

        GLES30.glActiveTexture(GLES30.GL_TEXTURE0)
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureId)
        var vTextureLocation = GLES30.glGetUniformLocation(programId, "vTexture")
        GLES30.glUniform1i(vTextureLocation, 0)
        GLES30.glDrawElements(GLES30.GL_TRIANGLES, 6, GLES30.GL_UNSIGNED_INT, 0)

        GLES30.glBindVertexArray(0)
    }

    override fun onSurfaceChanged(width: Int, height: Int) {
        GLES30.glViewport(0, 0, width, height)
//        projectionMatrix = getProjectionMatrix(width, height)
        projectionMatrix = getProjectionMatrix(
            width,
            height,
            bitmapSrc.width,
            bitmapSrc.height
        )
    }
}

 

  3.把shader应用到GLSurfaceView的回到函数中就行了

  

标签:正交投影,1.0,OpenGL,ES,1f,var,aspectRatio,GL,GLES30
From: https://www.cnblogs.com/tony-yang-flutter/p/18404851

相关文章

  • 计算机毕业设计nodejs+vue+express高校学生摄影社团管理系统 2ix7i
    目录技术栈具体实现截图系统设计解决的思路nodejs类核心代码部分展示可行性论证研究方法操作可行性源码获取技术栈该系统将采用B/S结构模式,开发软件有很多种可以用,本次开发用到的软件是vscode,用到的数据库是MySQL,为了更加便捷地使用数据库,用到了MySQL的可视化工具SQ......
  • Rancher 与 Kubernetes(K8s)的关系
    1. 简介1.1Kubernetes作为容器编排平台        Kubernetes是一个开源平台,用于自动化部署、扩展和管理容器化的应用。它提供了容器调度、自动伸缩、健康检查、滚动更新等功能。        例子:假设您有一个微服务架构的应用程序,需要运行在多个节点上,并且......
  • COSC3088 Essentials of IT and Ethics
    COSC3088EssentialsofITandEthicsAssessmentTask2:MultimediaLinkedInResourceCourseCode: COSC3088Weighting: Thisassessmentisworth40%ofyourfinalmarkforthisCourseLength: 1000-wordvisualresourceora3-minutevideo(+/-10%)Taskappr......
  • 1 件全新6ES7314-6EH04-0AB0 6ES73146EH040AB0 中央处理单元
    6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元引脚线6ES7314-6EH04-0AB06ES73146EH040AB0中央处理单元说明书......
  • Python3+requests搭建接口自动化测试框架_python3 import requests
    框架理念:使用json文件编写测试用例,建一个脚本循环读取测试用例并执行,然后对比返回的接口和用例中的期望结果。将测试结果写入到一个excel表格中生成测试报告,最后使用发送邮件功能将测试报告发送到指定邮箱。其中对所有公共方法进行封装并放在common公共文件目录下。  ......
  • [Typescript] Toggle full screen
    constrequestFullscreenProps=["requestFullScreen","webkitRequestFullScreen","mozRequestFullScreen","msRequestFullScreen",]asconst;constexitFullScreenProps=["exitFullscreen","......
  • @ConfigurationProperties VS @Value,你觉得哪个更好用
    文章目录使用测试@ConfigurationProperties和@Value区别复杂类型封装松散绑定元数据支持SpEL表达式JSR-303数据校验总结实际工作中,我们经常会看到或用到@ConfigurationProperties和@Value注解来注入自定义配置属性,那它们之间有什么不同呢?本文将从松散绑定、参数校验、SpEL表达......
  • 如何在 Nuxt 3 中有效使用 TypeScript
    title:如何在Nuxt3中有效使用TypeScriptdate:2024/9/9updated:2024/9/9author:cmdragonexcerpt:摘要:本文详细介绍了如何在Nuxt3项目中有效使用TypeScript,包括创建新项目、安装TypeScript依赖、进行类型检查、配置自动类型检查、使用自动生成的类型文件、实现更严......
  • Flutter 3.24 构建 release 抛出部分依赖 AAPT: error: resource android:attr/lStar
    问题截图:一些讨论:https://github.com/transistorsoft/flutter_background_fetch/issues/369问题原因及解决方案:@Aziz-T该问题与插件的compileSdkVersion和targetSdkVersion有关。出现该问题的原因是部分插件的compileSdkVersion和targetSdkVersion版本过旧。请前往......
  • GIS大事件!Bentley收购Cesium
    9月6日,Cesium官方宣布加入Bentley。Bentley我们并不陌生。最初Acute3D被Bentley公司收购,旗下软件由Smart3DCapture转型到ContextCapture,现又改名iTwinCapture。如今又收购了Cesium。Cesium官方表示,Cesium开发平台与iTwin的结合将为自然和建筑环境数字孪生的构建提供了完......