1 前言

【OpenGL ES】绘制三角形 中介绍了绘制三角形的方法,【OpenGL ES】绘制正方形中介绍了绘制正方形的方法,本文将介绍绘制圆形的方法。

​ OpenGL 以点、线段、三角形为图元,没有提供绘制圆形的接口。要绘制圆形边框,必须通过割圆法逼近圆形;要绘制圆形的内部,必须通过三角形逼近圆形,如下图,是通过GL_TRIANGLE_FAN 模式逼近圆形。

​ 本文完整代码资源见→【OpenGL ES】绘制圆形

​ 项目目录如下:

2 案例

​ MainActivity.java

  1. package com.zhyan8.circle;
  2. import android.opengl.GLSurfaceView;
  3. import android.os.Bundle;
  4. import androidx.appcompat.app.AppCompatActivity;
  5. public class MainActivity extends AppCompatActivity {
  6. private GLSurfaceView mGlSurfaceView;
  7. @Override
  8. protected void onCreate(Bundle savedInstanceState) {
  9. super.onCreate(savedInstanceState);
  10. mGlSurfaceView = new MyGLSurfaceView(this);
  11. setContentView(mGlSurfaceView);
  12. mGlSurfaceView.setRenderer(new MyRender(this));
  13. }
  14. @Override
  15. protected void onResume() {
  16. super.onResume();
  17. mGlSurfaceView.onResume();
  18. }
  19. @Override
  20. protected void onPause() {
  21. super.onPause();
  22. mGlSurfaceView.onPause();
  23. }
  24. }

​ MyGLSurfaceView.java

  1. package com.zhyan8.circle;
  2. import android.content.Context;
  3. import android.opengl.GLSurfaceView;
  4. import android.util.AttributeSet;
  5. public class MyGLSurfaceView extends GLSurfaceView {
  6. public MyGLSurfaceView(Context context) {
  7. super(context);
  8. setEGLContextClientVersion(3);
  9. }
  10. public MyGLSurfaceView(Context context, AttributeSet attrs) {
  11. super(context, attrs);
  12. setEGLContextClientVersion(3);
  13. }
  14. }

​ MyRender.java

  1. package com.zhyan8.circle;
  2. import android.content.Context;
  3. import android.opengl.GLES30;
  4. import android.opengl.GLSurfaceView;
  5. import java.nio.FloatBuffer;
  6. import javax.microedition.khronos.egl.EGLConfig;
  7. import javax.microedition.khronos.opengles.GL10;
  8. public class MyRender implements GLSurfaceView.Renderer {
  9. private static final int VERTEX_NUM = 45;
  10. private FloatBuffer vertexBuffer;
  11. private GLUtils mGLUtils;
  12. public MyRender(Context context) {
  13. mGLUtils = new GLUtils(context);
  14. }
  15. @Override
  16. public void onSurfaceCreated(GL10 gl, EGLConfig eglConfig) {
  17. //设置背景颜色
  18. GLES30.glClearColor(0.1f, 0.2f, 0.3f, 0.4f);
  19. //编译着色器
  20. final int vertexShaderId = mGLUtils.compileShader(GLES30.GL_VERTEX_SHADER, R.raw.vertex_shader);
  21. final int fragmentShaderId = mGLUtils.compileShader(GLES30.GL_FRAGMENT_SHADER, R.raw.fragment_shader);
  22. //链接程序片段
  23. int programId = mGLUtils.linkProgram(vertexShaderId, fragmentShaderId);
  24. GLES30.glUseProgram(programId);
  25. }
  26. @Override
  27. public void onSurfaceChanged(GL10 gl, int width, int height) {
  28. //设置视图窗口
  29. GLES30.glViewport(0, 0, width, height);
  30. getFloatBuffer(width, height);
  31. }
  32. @Override
  33. public void onDrawFrame(GL10 gl) {
  34. //将颜色缓冲区设置为预设的颜色
  35. GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT);
  36. GLES30.glLineWidth(5);
  37. //启用顶点的数组句柄
  38. GLES30.glEnableVertexAttribArray(0);
  39. //准备坐标数据
  40. GLES30.glVertexAttribPointer(0, 3, GLES30.GL_FLOAT, false, 0, vertexBuffer);
  41. // GLES30.glDrawArrays(GLES30.GL_POINTS, 0, VERTEX_NUM); //绘制圆形的顶点
  42. // GLES30.glDrawArrays(GLES30.GL_LINE_LOOP, 0, VERTEX_NUM); //绘制圆形的边
  43. GLES30.glDrawArrays(GLES30.GL_TRIANGLE_FAN, 0, VERTEX_NUM); //绘制圆形的内部
  44. //禁止顶点数组句柄
  45. GLES30.glDisableVertexAttribArray(0);
  46. }
  47. private void getFloatBuffer(int width, int height) {
  48. float[] vertex = mGLUtils.getCircle(0, 0, 0.75f, VERTEX_NUM);
  49. float[] tempVertex = mGLUtils.adjustCoord(vertex, width, height);
  50. vertexBuffer = mGLUtils.getFloatBuffer(tempVertex);
  51. }
  52. }

​ GLUtils.java

  1. package com.zhyan8.circle;
  2. import android.content.Context;
  3. import android.opengl.GLES30;
  4. import java.io.BufferedReader;
  5. import java.io.InputStream;
  6. import java.io.InputStreamReader;
  7. import java.nio.ByteBuffer;
  8. import java.nio.ByteOrder;
  9. import java.nio.FloatBuffer;
  10. import java.util.Arrays;
  11. public class GLUtils {
  12. private Context mContext;
  13. public GLUtils(Context context) {
  14. mContext = context;
  15. }
  16. //获取圆周上散点坐标
  17. public float[] getCircle(float centerX, float centerY, float radius, int num) {
  18. float unit = (float)(2 * Math.PI / num);
  19. float[] coords = new float[num * 3];
  20. for (int i = 0; i < num; i++) {
  21. coords[i * 3] = (float)(centerX + radius * Math.cos(unit * i));
  22. coords[i * 3 + 1] = (float)(centerY + radius * Math.sin(unit * i));
  23. coords[i * 3 + 2] = 0;
  24. }
  25. return coords;
  26. }
  27. //调整坐标
  28. public float[] adjustCoord(float[] coords, int width, int height) {
  29. float ratio = width > height ? (1.0f * height / width) : (1.0f * width / height);
  30. int start = width > height ? 0 : 1;
  31. float[] tempCoord = Arrays.copyOf(coords, coords.length);
  32. int num = tempCoord.length / 3;
  33. for (int i = 0; i < num; i++) {
  34. tempCoord[start + i * 3] *= ratio;
  35. }
  36. return tempCoord;
  37. }
  38. public FloatBuffer getFloatBuffer(float[] floatArr) {
  39. FloatBuffer fb = ByteBuffer.allocateDirect(floatArr.length * Float.BYTES)
  40. .order(ByteOrder.nativeOrder())
  41. .asFloatBuffer();
  42. fb.put(floatArr);
  43. fb.position(0);
  44. return fb;
  45. }
  46. //通过代码片段编译着色器
  47. public int compileShader(int type, String shaderCode){
  48. int shader = GLES30.glCreateShader(type);
  49. GLES30.glShaderSource(shader, shaderCode);
  50. GLES30.glCompileShader(shader);
  51. return shader;
  52. }
  53. //通过外部资源编译着色器
  54. public int compileShader(int type, int shaderId){
  55. String shaderCode = readShaderFromResource(shaderId);
  56. return compileShader(type, shaderCode);
  57. }
  58. //链接到着色器
  59. public int linkProgram(int vertexShaderId, int fragmentShaderId) {
  60. final int programId = GLES30.glCreateProgram();
  61. //将顶点着色器加入到程序
  62. GLES30.glAttachShader(programId, vertexShaderId);
  63. //将片元着色器加入到程序
  64. GLES30.glAttachShader(programId, fragmentShaderId);
  65. //链接着色器程序
  66. GLES30.glLinkProgram(programId);
  67. return programId;
  68. }
  69. //从shader文件读出字符串
  70. private String readShaderFromResource(int shaderId) {
  71. InputStream is = mContext.getResources().openRawResource(shaderId);
  72. BufferedReader br = new BufferedReader(new InputStreamReader(is));
  73. String line;
  74. StringBuilder sb = new StringBuilder();
  75. try {
  76. while ((line = br.readLine()) != null) {
  77. sb.append(line);
  78. sb.append("\n");
  79. }
  80. br.close();
  81. } catch (Exception e) {
  82. e.printStackTrace();
  83. }
  84. return sb.toString();
  85. }
  86. }

​ vertex_shader.glsl

  1. #version 300 es
  2. layout (location = 0) in vec4 vPosition;
  3. void main() {
  4. gl_Position = vPosition;
  5. gl_PointSize = 20.0; //顶点大小(GL_POINTS模式下才会生效)
  6. }

​ 顶点着色器的作用:进行矩阵变换位置、根据光照公式计算顶点颜⾊⽣成 / 变换纹理坐标,并且把位置和纹理坐标发送到片元着色器。

​ 顶点着色器中,如果没有指定默认精度,则 int 和 float 的默认精度都为 highp。

​ fragment_shader.glsl

  1. #version 300 es
  2. precision mediump float; //声明float型变量的精度为mediump
  3. out vec4 fragColor;
  4. void main() {
  5. fragColor = vec4(0.2, 1.0, 1.0, 1.0); //顶点、边线、内部填充颜色
  6. }

​ 片元着色器的作用:处理经光栅化阶段生成的每个片元,计算每个像素的颜色和透明度。

​ 在片元着色器中,浮点值没有默认的精度值,每个着色器必须声明一个默认的 float 精度。

运行结果:

​ 1)GL_POINTS 模式

​ 2)GL_LINE_LOOP 模式

​ 3)GL_TRIANGLE_FAN 模式

​ 声明:本文转自【OpenGL ES】绘制圆形

【OpenGL ES】绘制圆形的更多相关文章

  1. 【AR实验室】OpenGL ES绘制相机(OpenGL ES 1.0版本)

    0x00 - 前言 之前做一些移动端的AR应用以及目前看到的一些AR应用,基本上都是这样一个套路:手机背景显示现实场景,然后在该背景上进行图形学绘制.至于图形学绘制时,相机外参的解算使用的是V-SLA ...

  2. 使用OpenGL ES绘制3D图形

    如果应用定义的顶点不在同一个平面上,并且使用三角形把合适的顶点连接起来,就可以绘制出3D图形了. 使用OpenGL  ES绘制3D图形的方法与绘制2D图形的步骤大致相同,只是绘制3D图形需要定义更多的 ...

  3. 【Qt for Android】OpenGL ES 绘制彩色立方体

    Qt 内置对OpenGL ES的支持.选用Qt进行OpenGL ES的开发是很方便的,很多辅助类都已经具备.从Qt 5.0開始添加了一个QWindow类,该类既能够使用OpenGL绘制3D图形,也能够 ...

  4. 2.x最终照着教程,成功使用OpenGL ES 绘制纹理贴图,添加了灰度图

    在之前成功绘制变色的几何图形之后,今天利用Openg ES的可编程管线绘制出第一张纹理. 学校时候不知道OpenGL的重要性,怕晦涩的语法.没有跟老师学习OpenGL的环境配置,现在仅仅能利用coco ...

  5. Android OpenGL ES 开发(四): OpenGL ES 绘制形状

    在上文中,我们使用OpenGL定义了能够被绘制出来的形状了,现在我们想绘制出来它们.使用OpenGLES 2.0来绘制形状会比你想象的需要更多的代码.因为OpenGL的API提供了大量的对渲染管线的控 ...

  6. Opengl ES之四边形绘制

    四边形的绘制在Opengl ES是很重要的一项技巧,比如做视频播放器时视频的渲染就需要使用到Opengl ES绘制四边形的相关知识.然而在Opengl ES却没有直接提供 绘制四边形的相关函数,那么如 ...

  7. OpenGL ES: (5) OpenGL的基本概念、OpenGL ES 在屏幕产生图片的过程、OpenGL管线(pipeline)

    一. OpenGL的基本概念 OpenGL 的结构可以从逻辑上划分为下面 3 个部分: 图元(Primitives) 缓冲区(Buffers) 光栅化(Rasterize) 图元(Primitives ...

  8. OpenGL ES应用开发实践指南:iOS卷

    <OpenGL ES应用开发实践指南:iOS卷> 基本信息 原书名:Learning OpenGL ES for iOS:A Hands-On Guide to Modern 3D Gra ...

  9. Android OpenGL ES(四)关于EGL .

    OpenGL ES的javax.microedition.khronos.opengles 包定义了平台无关的GL绘图指令,EGL(javax.microedition.khronos.egl ) 则 ...

  10. 【Android Developers Training】 62. 搭建一个OpenGL ES环境

    注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好. 原文链接:http://developer ...

随机推荐

  1. 第二届福州大学至诚学院网络安全大赛G0DCTF Misc WP

    MISC baby_misc 1.题目信息 key文件夹: 还有一张图片 2.解题方法 观察key文件夹里的每个文件信息,发现并无什么有用的,甚至有的为空... 看到文件名称的数字而且还给了图片,可以 ...

  2. [转帖]umount -fl用法

    https://www.cnblogs.com/xingmuxin/p/8446178.html umount, 老是提示:device is busy, 服务又不能停止的.可以用"umou ...

  3. 使用Grafana + jmx 监控 kafka3.5 的过程

    使用Grafana + jmx 监控 kafka3.5 的过程 摘要 周五一边进行数据库监控, 同时想着部署一套监控系统. 能够监控一下kafka等中间件 结果不想自己遇到了很多坑. 下午有同事语音告 ...

  4. [转帖]88. sys_kwr

    88. sys_kwr ¶ 88.1. 插件sys_kwr简介 ¶ 插件sys_kwr是KingbaseES 的一个扩展插件.主要功能是通过周期性自动记录性能统计相关的快照,分析出KingbaseES ...

  5. Springboot 数据库连接池大小简单总结

    最近在进行性能压测, 想验证一下产品的极限性能, 在使用openpower 2路22核(SMT4)176线程 512G内存的服务器上面进行性能压测 压测进行到1000并发或者是2000并发时性能有一定 ...

  6. CTT Day3

    T1 忘了叫什么名字 对于一个排列 \(p\),定义它的权值为其有多少个子串是一个值域从 \(1\) 开始的排列.给定排列 \(p\),对于 \(1\le i\le j\le n\),定义 \(f(i ...

  7. css3只需一招,将网站变成灰色的

    今天大家在浏览B站,腾讯视频,等网站时,有没有发现一个现象,网站变成灰色的了. 是不是跟平常不一样了呢,这是因为今天(2020.4.4)是全国哀悼日, 所以网站这些就变成灰色的呢. 我去看了一下腾讯的 ...

  8. 【JS 逆向百例】HN某服务网登录逆向,验证码形同虚设

    声明 本文章中所有内容仅供学习交流,抓包内容.敏感网址.数据接口均已做脱敏处理,严禁用于商业用途和非法用途,否则由此产生的一切后果均与作者无关,若有侵权,请联系我立即删除! 逆向目标 目标:某政务服务 ...

  9. 在K8S中各个组件及其作用?

    Kubernetes(简称K8s)是一个强大的容器编排系统,其主要组件及其作用如下: kube-apiserver: 集群的主入口点,提供了RESTful API接口供用户或内部组件与集群进行交互.它 ...

  10. [置顶] Gin--Begoo框架快速指南

    Gin篇 第一篇: Gin-官方文档 第二篇: Gin-安装,修改启动端口,get/post 请求参数,模型绑定shouldbind,自定义验证器/表单验证 第三篇: Gin-上传文件/返回前端.中间 ...