Android OpenGL ES详解——绘制圆角矩形

目录

 1、绘制矩形

Renderer基类

矩形Renderer类

顶点着色器

片元着色器

2、绘制圆形

圆形Renderer类

顶点着色器

片元着色器

3、绘制圆角矩形

圆角矩形Renderer类

顶点着色器

片元着色器

4、源码下载


 1、绘制矩形

Renderer基类

代码如下:

package com.example.roundrect.renderers

import android.content.Context
import android.opengl.GLES30
import android.opengl.GLSurfaceView.Renderer
import com.example.roundrect.R
import com.example.roundrect.program.RoundRectShaderProgram
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

open class BaseRenderer(context: Context) : Renderer {
    var mShaderProgram: RoundRectShaderProgram? = null
    var mContext = context

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
        mShaderProgram = RoundRectShaderProgram(
            mContext,
            R.raw.roundrect_vertex_shader,
            R.raw.roundrect_fragment_shader
        )
        mShaderProgram?.useProgram()
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        var side = Math.min(width, height)
        GLES30.glViewport(0, 0, side, side)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)

    }
}

矩形Renderer类

代码如下:

package com.example.roundrect

import android.content.Context
import android.opengl.GLES30
import android.opengl.GLSurfaceView.Renderer
import com.opengllib.data.VertexArray
import com.opengllib.programs.ShaderProgram
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10

class RoundRectRenderer(context: Context) : Renderer {
    private var mVertices = floatArrayOf(
        -0.5f, -0.5f,
        0.5f, 0.5f,
        -0.5f, 0.5f,
        -0.5f, -0.5f,
        0.5f, -0.5f,
        0.5f, 0.5f,
    )
    private var mShaderProgram: ShaderProgram? = null
    private var mContext = context
    private var mVertexArray: VertexArray? = null

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(0.6f, 0.7f, 0.8f, 1.0f)
        mVertexArray = VertexArray(mVertices)

        mShaderProgram = ShaderProgram(
            mContext,
            R.raw.roundrect_vertex_shader,
            R.raw.roundrect_fragment_shader
        )
        mShaderProgram?.useProgram()
        mVertexArray?.setVertexAttribPointer(
            0,
            mShaderProgram?.getPositionAttributeLocation()!!,
            2,
            0
        )

    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        GLES30.glViewport(0, 0, width, height)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,0 ,mVertices.size / 2)
    }
}

顶点着色器

roundrect_vertex_shader.glsl代码如下:

attribute vec4 a_Position;

void main()
{
    gl_Position = a_Position;
}

片元着色器

roundrect_fragment_shader.glsl代码如下:

precision mediump float;

void main()
{
	gl_FragColor = vec4(0.8, 0.5, 0.3, 1.0);
}

2、绘制圆形

圆形Renderer类

代码如下:

package com.example.roundrect.renderers

import android.content.Context
import android.opengl.GLES30
import com.example.roundrect.Constant
import com.opengllib.data.VertexArray
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import kotlin.math.cos
import kotlin.math.sin

open class CirclarRenderer(context: Context) : BaseRenderer(context) {
    var mVerticesCircle: FloatArray? = null
    var mCirclarVertexArray: VertexArray? = null

    init {
        mVerticesCircle = createCircle(0.5f, 100)
    }

    fun createCircle(radius: Float, n: Int): FloatArray? {
        val data = ArrayList<Float>()
        data.add(0.45f) //设置圆心坐标
        data.add(0.45f)
        val angDegSpan = 360f / n
        var i = 0f
        while (i < 360 + angDegSpan) {
            data.add((radius * sin(i * Math.PI / 180f)).toFloat()+0.45f)
            data.add((radius * cos(i * Math.PI / 180f)).toFloat()+0.45f)
            i += angDegSpan
        }
        val f = FloatArray(data.size)
        for (i in f.indices) {
            f[i] = data[i]
        }
        return f
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        super.onSurfaceCreated(gl, config)
        mCirclarVertexArray = VertexArray(mVerticesCircle!!)
        mCirclarVertexArray?.setVertexAttribPointer(
            0,
            mShaderProgram?.getPositionAttributeLocation()!!,
            Constant.POSITION_COMPONENT_COUNT,
            0
        )
    }

    override fun onDrawFrame(gl: GL10?) {
        super.onDrawFrame(gl)
        //绘制圆形
        GLES30.glUniform4f(mShaderProgram!!.getColorUniformLocation(), 0.0f, 0.0f, 1.0f, 0.5f)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, mVerticesCircle?.size!! / 2);
    }
}

顶点着色器

roundrect_vertex_shader.glsl代码如下:

attribute vec4 a_Position;

void main()
{
    gl_Position = a_Position;
}

片元着色器

roundrect_fragment_shader.glsl代码如下:

precision mediump float;

void main()
{
	gl_FragColor = vec4(0.8, 0.5, 0.3, 1.0);
}

3、绘制圆角矩形

圆角矩形Renderer类

代码如下:

package com.example.roundrect.renderers

import android.content.Context
import android.opengl.GLES30
import com.example.roundrect.Constant
import com.example.roundrect.R
import com.example.roundrect.program.RoundRectShaderProgram
import com.opengllib.data.VertexArray
import javax.microedition.khronos.egl.EGLConfig
import javax.microedition.khronos.opengles.GL10
import kotlin.math.cos
import kotlin.math.sin

class CirclarRectRenderer(context: Context) : CirclarRenderer(context) {
    private val CIRLAR_COUNT = 100
    private val RADIUS = 0.05f
    private var mVertices = floatArrayOf(
        -0.5f, -0.8f,
        0.5f, 0.8f,
        -0.5f, 0.8f,

        -0.5f, -0.8f,
        0.5f, -0.8f,
        0.5f, 0.8f
    )

    init {
        mVerticesCircle = createCirclarRect(RADIUS, CIRLAR_COUNT)
    }

    fun createCirclarRect(radius: Float, n: Int): FloatArray? {
        val data = ArrayList<Float>()
        for (index in mVertices.indices) {
            data.add(mVertices[index])
        }
        //右圆形
        data.add(0.5f - radius) //设置圆心坐标
        data.add(0.85f - radius)
        val angDegSpan = 360f / n
        var i = 0f
        while (i < 360 + angDegSpan) {
            data.add((radius * sin(i * Math.PI / 180f)).toFloat() + (0.5f - radius))
            data.add((radius * cos(i * Math.PI / 180f)).toFloat() + (0.5f - radius))
            i += angDegSpan
        }
        //左圆形
        data.add(-0.5f + radius) //设置圆心坐标
        data.add(-0.8f + radius)
        val angDegSpanL = 360f / n
        var iL = 0f
        while (iL < 360 + angDegSpanL) {
            data.add((radius * sin(iL * Math.PI / 180f)).toFloat() + (-0.5f + radius))
            data.add((radius * cos(iL * Math.PI / 180f)).toFloat() + (-0.5f + radius))
            iL += angDegSpanL
        }
        data.add(-0.5f + radius) //设置圆心坐标
        data.add(0.8f - radius)
        val angDegSpanL2 = 360f / n
        var iL2 = 0f
        while (iL2 < 360 + angDegSpanL2) {
            data.add((radius * sin(iL2 * Math.PI / 180f)).toFloat() + (-0.5f + radius))
            data.add((radius * cos(iL2 * Math.PI / 180f)).toFloat() + (0.5f - radius))
            iL2 += angDegSpanL2
        }
        data.add(0.5f - radius) //设置圆心坐标
        data.add(-0.8f + radius)
        val angDegSpanR = 360f / n
        var iR = 0f
        while (iR < 360 + angDegSpanR) {
            data.add((radius * sin(iR * Math.PI / 180f)).toFloat() + (0.5f - radius))
            data.add((radius * cos(iR * Math.PI / 180f)).toFloat() + (-0.5f + radius))
            iR += angDegSpanR
        }
        val f = FloatArray(data.size)
        for (i in f.indices) {
            f[i] = data[i]
        }
        return f
    }

    override fun onSurfaceCreated(gl: GL10?, config: EGLConfig?) {
        GLES30.glClearColor(1.0f, 1.0f, 1.0f, 1.0f)
        mShaderProgram = RoundRectShaderProgram(
            mContext,
            R.raw.roundrect_vertex_shader,
            R.raw.roundrect_fragment_shader
        )
        mShaderProgram?.useProgram()

        mCirclarVertexArray = VertexArray(mVerticesCircle!!)
        mCirclarVertexArray?.setVertexAttribPointer(
            0,
            mShaderProgram?.getPositionAttributeLocation()!!,
            Constant.POSITION_COMPONENT_COUNT,
            0
        )
    }

    override fun onSurfaceChanged(gl: GL10?, width: Int, height: Int) {
        super.onSurfaceChanged(gl, width, height)
    }

    override fun onDrawFrame(gl: GL10?) {
        GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT)
        GLES30.glUniform4f(mShaderProgram!!.getColorUniformLocation(), 0.0f, 1.0f, 0.0f, 0.5f)
        //绘制矩形
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, 6)
        //绘制圆形
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 7, CIRLAR_COUNT)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 7 + CIRLAR_COUNT + 2, CIRLAR_COUNT)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 7 + CIRLAR_COUNT * 2 + 4, CIRLAR_COUNT)
        GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 7 + CIRLAR_COUNT * 3 + 6, CIRLAR_COUNT)
    }
}

顶点着色器

roundrect_vertex_shader.glsl代码如下:

attribute vec4 a_Position;

varying vec2 vRectCoord;

void main()
{
    vRectCoord = vec2(a_Position.x, a_Position.y);
    gl_Position = a_Position;
}

片元着色器

roundrect_fragment_shader.glsl代码如下:

precision mediump float;
uniform vec4 u_Color;
varying vec2 vRectCoord;

void main()
{
    if(abs(vRectCoord.x) > 0.45 && abs(vRectCoord.y) > 0.75
     && sqrt(
     (abs(vRectCoord.x) -0.45)*(abs(vRectCoord.x) -0.45)
     + (abs(vRectCoord.y) -0.75)*(abs(vRectCoord.y) -0.75)
     ) > 0.05){
       gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0);
    } else {
       gl_FragColor = u_Color;
    }
}

4、源码下载

Android OpenGL ES绘制矩形、圆形和圆角矩形演示demo源码下载地址:

https://download.youkuaiyun.com/download/github_27263697/90058907

参考文章

OpenGL ES之六——绘制矩形和圆形_gles20 画圆-优快云博客

使用OpenGL实现圆角效果-腾讯云开发者社区-腾讯云

[原]shader实现矩形圆角 - U_探索 - 博客园

Opengl: 使用glsl 将纹理处理成圆角的几种思路 - 连山In17 - 博客园

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闲暇部落

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值