当前位置: 首页 > wzjs >正文

网站建设蓝色工匠郑州市金水区建设局官方网站

网站建设蓝色工匠,郑州市金水区建设局官方网站,中国知名公司,唐河网站制作公司GLSurfaceView绘制图形拉伸问题 假如在XML文件中声明GLSurfaceView的宽高为 android:layout_width"match_parent"android:layout_height"match_parent GLSurfaceView绘制的图形在Open GL ES坐标系中,而Open GL ES坐标系会根据GLSurfaceView的宽高将…

GLSurfaceView绘制图形拉伸问题

  • 假如在XML文件中声明GLSurfaceView的宽高为
    • android:layout_width="match_parent"
    • android:layout_height="match_parent
  • GLSurfaceView绘制的图形在Open GL ES坐标系中,而Open GL ES坐标系会根据GLSurfaceView的宽高将绘制的图形拉伸,比如绘制一个正方形,有可能绘制成矩形,解决方案:
  • Matrix.frustumM透视投影解决
  • Matrix.orthoM正交投影解决
// 透视投影矩阵
public static void frustumM(float[] m, int offset,float left, float right, float bottom, float top,float near, float far) {}// 正交投影矩阵
public static void orthoM(float[] m, int mOffset,float left, float right, float bottom, float top,float near, float far) {}

OpenGL ES坐标系

在这里插入图片描述

XML文件

<?xml version="1.0" encoding="utf-8"?>
<com.example.myapplication.MyGLSurfaceViewxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent" />

绘制拉伸正方形

自定义GLSurfaceView代码

class MyGLSurfaceView(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs) {private var mRenderer = MyGLRenderer()init {// 设置 OpenGL ES 3.0 版本setEGLContextClientVersion(3)setRenderer(mRenderer)// 设置渲染模式, 仅在需要重新绘制时才进行渲染,以节省资源renderMode = RENDERMODE_WHEN_DIRTY}
}

自定义GLSurfaceView.Renderer代码

class MyGLRenderer : GLSurfaceView.Renderer {private var mDrawData: DrawData? = nulloverride fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {// 当 Surface 创建时调用, 进行 OpenGL ES 环境的初始化操作, 设置清屏颜色为青蓝色 (Red=0, Green=0.5, Blue=0.5, Alpha=1)GLES30.glClearColor(0.0f, 0.5f, 0.5f, 1.0f)mDrawData = DrawData().apply {initVertexBuffer()initShader()}}override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {// 当 Surface 尺寸发生变化时调用,例如设备的屏幕方向发生改变, 设置视口为新的尺寸,视口是指渲染区域的大小GLES30.glViewport(0, 0, width, height)}override fun onDrawFrame(gl: GL10?) {// 每一帧绘制时调用, 清除颜色缓冲区GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)mDrawData?.drawSomething()}
}

GLSurfaceView需要的绘制数据

class DrawData{var mProgram : Int = -1var NO_OFFSET = 0var VERTEX_POS_DATA_SIZE = 3// 1. 准备正方形的顶点数据Float数组, 分配顶点数据Float数组的直接内存val vertex = floatArrayOf(-0.5f,  0.5f, 0.0f, // 左上-0.5f, -0.5f, 0.0f, // 左下0.5f, 0.5f, 0.0f, // 右上0.5f, -0.5f, 0.0f, // 右下)val vertexBuffer = ByteBuffer.allocateDirect(vertex.size * 4) // 分配直接内存.order(ByteOrder.nativeOrder()) // 使用小端, 即低地址存放低位数据, 高地址存放高位数据.asFloatBuffer()// 2. 创建顶点缓冲区对象(Vertex Buffer Object, VBO), 并上传顶点数据到缓冲区对象中fun initVertexBuffer(){vertexBuffer.put(vertex) // 将顶点数据放入 FloatBuffervertexBuffer.position(0) // 在将数据放入缓冲区后,位置指针会指向缓冲区的末尾。重置位置指针为 0,使得在后续操作中可以从缓冲区的开始位置读取数据val vbo = IntArray(1)GLES30.glGenBuffers(1, vbo, 0) // 生成一个缓冲区对象ID,并存储在数组 vbo 中,存放位置为0GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]) // 绑定生成的顶点缓冲区对象,使其成为当前缓冲区操作的目标GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertex.size * 4, // 数据总字节数 = 顶点数 * Float占4字节vertexBuffer,GLES30.GL_STATIC_DRAW)}fun initShader()  {val vertexShaderCode = """#version 300 eslayout (location = 0) in vec4 aPosition;void main() {gl_Position = aPosition;}""".trimIndent()         // 顶点着色器代码val fragmentShaderCode = """#version 300 esprecision mediump float;uniform vec4 vColor;out vec4 fragColor;void main() {fragColor = vColor;}""".trimIndent()         // 片段着色器代码// 3. 加载顶点着色器和片段着色器, 并创建着色器程序val vertexShader = LoadShaderUtil.loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode)val fragmentShader = LoadShaderUtil.loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode)mProgram = GLES30.glCreateProgram()GLES30.glAttachShader(mProgram, vertexShader)GLES30.glAttachShader(mProgram, fragmentShader)GLES30.glLinkProgram(mProgram)GLES30.glUseProgram(mProgram)}// 4. 使用着色器程序绘制图形fun drawSomething(){// 5. 获取顶点数据的位置, 并使用该位置的数据val positionHandle = GLES30.glGetAttribLocation(mProgram, "aPosition")GLES30.glEnableVertexAttribArray(positionHandle)GLES30.glVertexAttribPointer(positionHandle, VERTEX_POS_DATA_SIZE, GLES30.GL_FLOAT, false, 0, 0)// 6. 设置片段着色器的颜色val colorHandle = GLES30.glGetUniformLocation(mProgram, "vColor")GLES30.glUniform4f(colorHandle, 1.0f, 0.5f, 0.5f, 1.0f) // 红色// 7. 绘制正方形GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, NO_OFFSET, vertex.size / VERTEX_POS_DATA_SIZE)GLES30.glDisableVertexAttribArray(positionHandle)}
}object LoadShaderUtil{// 创建着色器对象fun loadShader(type: Int, source: String): Int {val shader = GLES30.glCreateShader(type)GLES30.glShaderSource(shader, source)GLES30.glCompileShader(shader)return shader}
}

效果图

在这里插入图片描述

透视投影绘制不拉伸的正方形

透视投影PerspectiveProjection

自定义GLSurfaceView代码

class MyGLSurfaceView(context: Context, attrs: AttributeSet) : GLSurfaceView(context, attrs) {private var mRenderer = MyGLRenderer()init {// 设置 OpenGL ES 3.0 版本setEGLContextClientVersion(3)setRenderer(mRenderer)// 设置渲染模式, 仅在需要重新绘制时才进行渲染,以节省资源renderMode = RENDERMODE_WHEN_DIRTY}
}

自定义GLSurfaceView.Renderer代码

class MyGLRenderer : GLSurfaceView.Renderer {private var mDrawData: DrawDataWithPerspectiveProjection? = nulloverride fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {// 当 Surface 创建时调用, 进行 OpenGL ES 环境的初始化操作, 设置清屏颜色为青蓝色 (Red=0, Green=0.5, Blue=0.5, Alpha=1)GLES30.glClearColor(0.0f, 0.5f, 0.5f, 1.0f)mDrawData = DrawDataWithPerspectiveProjection().apply {initVertexBuffer()initShader()}}override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {// 当 Surface 尺寸发生变化时调用,例如设备的屏幕方向发生改变, 设置视口为新的尺寸,视口是指渲染区域的大小GLES30.glViewport(0, 0, width, height)mDrawData?.computeMVPMatrix(width.toFloat(), height.toFloat())}override fun onDrawFrame(gl: GL10?) {// 每一帧绘制时调用, 清除颜色缓冲区GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)mDrawData?.drawSomething()}
}

GLSurfaceView需要的绘制数据

class DrawDataWithPerspectiveProjection {var mProgram : Int = -1var NO_OFFSET = 0var VERTEX_POS_DATA_SIZE = 3// 1. 准备正方形的顶点数据Float数组, 分配顶点数据Float数组的直接内存val vertex = floatArrayOf(-0.5f,  0.5f, 0.0f, // 左上-0.5f, -0.5f, 0.0f, // 左下0.5f, 0.5f, 0.0f, // 右上0.5f, -0.5f, 0.0f, // 右下)val vertexBuffer = ByteBuffer.allocateDirect(vertex.size * 4) // 分配直接内存.order(ByteOrder.nativeOrder()) // 使用小端, 即低地址存放低位数据, 高地址存放高位数据.asFloatBuffer()// 2. 创建顶点缓冲区对象(Vertex Buffer Object, VBO), 并上传顶点数据到缓冲区对象中fun initVertexBuffer(){vertexBuffer.put(vertex) // 将顶点数据放入 FloatBuffervertexBuffer.position(0) // 在将数据放入缓冲区后,位置指针会指向缓冲区的末尾。重置位置指针为 0,使得在后续操作中可以从缓冲区的开始位置读取数据val vbo = IntArray(1)GLES30.glGenBuffers(1, vbo, 0) // 生成一个缓冲区对象ID,并存储在数组 vbo 中,存放位置为0GLES30.glBindBuffer(GLES30.GL_ARRAY_BUFFER, vbo[0]) // 绑定生成的顶点缓冲区对象,使其成为当前缓冲区操作的目标GLES30.glBufferData(GLES30.GL_ARRAY_BUFFER,vertex.size * 4, // 数据总字节数 = 顶点数 * Float占4字节vertexBuffer,GLES30.GL_STATIC_DRAW)}fun initShader()  {val vertexMapShaderCode = """#version 300 esuniform mat4 uMVPMatrix;layout (location = 0) in vec4 aPosition;void main() {gl_Position = uMVPMatrix * aPosition;}""".trimIndent()val fragmentShaderCode = """#version 300 esprecision mediump float;uniform vec4 vColor;out vec4 fragColor;void main() {fragColor = vColor;}""".trimIndent()         // 片段着色器代码// 3. 加载顶点着色器和片段着色器, 并创建着色器程序val vertexShader = LoadShaderUtil.loadShader(GLES30.GL_VERTEX_SHADER, vertexMapShaderCode)val fragmentShader = LoadShaderUtil.loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode)mProgram = GLES30.glCreateProgram()GLES30.glAttachShader(mProgram, vertexShader)GLES30.glAttachShader(mProgram, fragmentShader)GLES30.glLinkProgram(mProgram)GLES30.glUseProgram(mProgram)}// 4. 使用着色器程序绘制图形fun drawSomething(){// 新增矩阵传递代码val matrixHandle = GLES30.glGetUniformLocation(mProgram, "uMVPMatrix")GLES30.glUniformMatrix4fv(matrixHandle, 1, false, mMVPMatrix, 0)// 5. 获取顶点数据的位置, 并使用该位置的数据val positionHandle = GLES30.glGetAttribLocation(mProgram, "aPosition")GLES30.glEnableVertexAttribArray(positionHandle)GLES30.glVertexAttribPointer(positionHandle, VERTEX_POS_DATA_SIZE, GLES30.GL_FLOAT, false, 0, 0)// 6. 设置片段着色器的颜色val colorHandle = GLES30.glGetUniformLocation(mProgram, "vColor")GLES30.glUniform4f(colorHandle, 1.0f, 0.5f, 0.5f, 1.0f) // 红色// 7. 绘制正方形GLES30.glDrawArrays(GLES30.GL_TRIANGLE_STRIP, NO_OFFSET, vertex.size / VERTEX_POS_DATA_SIZE)GLES30.glDisableVertexAttribArray(positionHandle)}// 最终变化矩阵private val mMVPMatrix = FloatArray(16)// 投影矩阵private val mProjectionMatrix = FloatArray(16)// 相机矩阵private val mViewMatrix = FloatArray(16)private var mViewPortRatio = 1ffun computeMVPMatrix(width: Float, height: Float) {// 1. 设置透视投影矩阵,为了让近平面宽高比与屏幕宽高比一致takeIf { width > height }?.let {mViewPortRatio = width / heightMatrix.frustumM(mProjectionMatrix, // 透视投影矩阵NO_OFFSET, // 偏移量-mViewPortRatio, // 近平面的坐标系左边界mViewPortRatio, // 近平面的坐标系右边界-1f, // 近平面的坐标系的下边界1f, // 近平面坐标系的上边界1f, // 近平面距离相机距离2f // 远平面距离相机距离)} ?: run {mViewPortRatio = height / widthMatrix.frustumM(mProjectionMatrix, // 透视投影矩阵NO_OFFSET, // 偏移量-1f, // 近平面坐标系左边界1f, // 近平面坐标系右边界-mViewPortRatio, // 近平面坐标系下边界mViewPortRatio, // 近平面坐标系上边界1f, // 近平面距离相机距离2f // 远平面距离相机距离)}// 2. 设置相机矩阵// 相机位置(0f, 0f, 1f)// 物体位置(0f, 0f, 0f)// 相机方向(0f, 1f, 0f)Matrix.setLookAtM(mViewMatrix, // 相机矩阵NO_OFFSET, // 偏移量0f, // 相机位置x0f, // 相机位置y1f, // 相机位置z0f, // 物体位置x0f, // 物体位置y0f, // 物体位置z0f, // 相机上方向x1f, // 相机上方向y0f // 相机上方向z)// 3. 设置最终变化矩阵Matrix.multiplyMM(mMVPMatrix, // 最终变化矩阵NO_OFFSET, // 偏移量mProjectionMatrix, // 投影矩阵NO_OFFSET, // 投影矩阵偏移量mViewMatrix, // 相机矩阵NO_OFFSET // 相机矩阵偏移量)}
}

效果图

在这里插入图片描述


文章转载自:

http://u4ZfoNFQ.skmpj.cn
http://fXz1Wxpj.skmpj.cn
http://bSJx2qb0.skmpj.cn
http://oZkSCTu6.skmpj.cn
http://USaZ5Emy.skmpj.cn
http://Q6rQPKNI.skmpj.cn
http://giQ7AlKj.skmpj.cn
http://h9HOCTBJ.skmpj.cn
http://TCsYwVBo.skmpj.cn
http://NVep7bAN.skmpj.cn
http://lftMwjZL.skmpj.cn
http://YyfLGd42.skmpj.cn
http://FR2SarRn.skmpj.cn
http://v7U450GH.skmpj.cn
http://gJxioDeq.skmpj.cn
http://G04g8AXO.skmpj.cn
http://kC7zTzWs.skmpj.cn
http://7QK1zLrg.skmpj.cn
http://7BMtbElR.skmpj.cn
http://YflPzDXY.skmpj.cn
http://dzGkFmt3.skmpj.cn
http://6eezU5s4.skmpj.cn
http://zi1xNCxw.skmpj.cn
http://imy79gLh.skmpj.cn
http://EWyjfFN4.skmpj.cn
http://hZcXC1BS.skmpj.cn
http://yu1S5rdc.skmpj.cn
http://7Au0QfvN.skmpj.cn
http://KAyk559z.skmpj.cn
http://HWDFvrwS.skmpj.cn
http://www.dtcms.com/wzjs/657887.html

相关文章:

  • 网站设计制作公司排名接入服务商网站备案管理系统技术规范要求
  • 做建设网站的活的兼职军人可以做网站吗
  • phpcms如何做装饰网站公司做网站流程流程
  • 嘉兴建设企业网站外包服务属于什么行业
  • 网站建设 中企动力 扬州公证网站建设管理
  • 淮安市汽车网站建设背景网络优化工程师实习报告
  • 工业设计网站外网北京企业网站制作
  • 网站域名备案证书小制作简单易学
  • 免费下载图片的网站有哪些东莞常平镇地图
  • 用了wordpress的网站顺德微信网站建设
  • 网站建设开发合同北京王府井在哪个区
  • 桥梁建设网站高邮建设银行网站
  • 安徽池州做企业网站wordpress mysql 安装
  • 郑州网站设计公司排名西安推广网站
  • 凡客建设网站稳定吗网站建设朋友圈
  • 电脑做网站服务器WIN7 买个域名wordpress 爬
  • 网站平面模板上海企业电话查询
  • 某某网站安全建设方案wordpress 转 html
  • 网站开发用什么数据库dedecmsv5.6 qq空间网站模板
  • 福州网站搭建洛阳建设网站的公司
  • 购物网站制作费用做的烂的网站
  • 网站备案相关前置许可企业网站建设主要包括哪些内容
  • 快递网站模版深圳定制开发公司
  • 贵州建设工程招投标协会网站网站开发 技术投标
  • 建网站的详细技术卢松松网站的百度广告怎么做的
  • 珠海网站制作报价建设外贸网站案例
  • 网站建设竞价托管服务网易企业邮箱服务器配置
  • 用dw设计网站模板下载介绍自己公司的范文
  • 生态农业网站建设方案肇庆网站快速排名优化
  • 做教育集团的网站建设微信开放平台介绍