OpenGLES:绘制一个混色旋转的3D圆柱
- 人工智能
- 2025-08-17 22:39:02

效果展示
本篇博文会实现两种混色效果的3D圆柱:
一.圆柱体解析上一篇博文讲解了怎么绘制一个混色旋转的立方体
这一篇讲解怎么绘制一个混色旋转的圆柱
圆柱的顶点创建主要基于2D圆进行扩展,与立方体没有相似之处
圆柱绘制的关键点就是将圆柱拆解成:两个Z坐标不为0的圆 + 一个长方形的圆柱面
绘制2D圆的过程这里不再复述,不理解的可以参看前面这篇博文:《OpenGLES:绘制一个颜色渐变的圆》
废话不多说,正文开始了。
二.GLRender:变量定义 2.1 常规变量定义 //着色器程序/渲染器 private int shaderProgram; //着色器mvp矩阵属性 private int mvpMatrix; //位置属性 private int aPositionLocation; //surface宽高比率 private float ratio; 2.2 定义顶点坐标数组和缓冲概述中提到过,绘制圆柱的关键思路是将圆柱拆解成:两个Z坐标不为0的圆 + 一个长方形的圆柱面
所以定义三个顶点坐标数组和对应缓冲
//圆柱柱面顶点数组 private float[] vertexData; //圆柱顶部圆的顶点数组 private float[] vertexData1; //圆柱底部圆的顶点数组 private float[] vertexData2; //圆柱柱面顶点缓冲 private FloatBuffer vertexBuffer; //圆柱顶部圆的顶点缓冲 private FloatBuffer vertexBuffer1; //圆柱顶部圆的顶点缓冲 private FloatBuffer vertexBuffer2;需要注意的是,这次我并没有把顶点颜色单独定义成一个数组,而且在Render类中也不会像上一篇绘制立方体时动态加载和填充顶点颜色值
这次我会换一种方式,直接把颜色填充和变换在着色器代码中实现
最终的色彩渐变效果是一样的,殊途同归,丰富对OpenGLES不同实现方式的学习。
2.3 定义MVP矩阵 //MVP矩阵 private float[] mMVPMatrix = new float[16]; 三.GLRender:着色器、内存分配等 3.1 着色器创建、链接、使用 3.2 着色器属性获取、赋值 3.3 缓冲内存分配这几个部分的代码实现2D图形绘制基本一致
可参考以前2D绘制的相关博文,里面都有详细的代码实现
不再重复展示代码
四.GLRender:动态创建顶点 float radio = 0.6f; int spanIdx = 60; vertexData = createSidePos(radio, spanIdx); vertexData1 = createBottomCirclePos(radio, spanIdx, 0.7f); vertexData2 = createBottomCirclePos(radio, spanIdx, -0.7f);重点就在于创建圆柱顶点的两个函数:
createSidePos()createBottomCirclePos() 4.1 createSidePos() private float[] createSidePos(float radius, int n) { ArrayList<Float> data = new ArrayList<>(); //设置顶部/底部圆的顶点坐标 float angDegSpan = 360f / n; for (float i = 0; i < 360 + angDegSpan; i += angDegSpan) { data.add((float) (radius * Math.sin(i * Math.PI / 180f))); data.add((float) (radius * Math.cos(i * Math.PI / 180f))); //顶部/底部圆的顶点Z坐标设置为-0.7f data.add(-0.7f); data.add((float) (radius * Math.sin(i * Math.PI / 180f))); data.add((float) (radius * Math.cos(i * Math.PI / 180f))); //顶部/底部圆的顶点Z坐标设置为-0.7f data.add(0.7f); } //所有顶点坐标 float[] f = new float[data.size()]; for (int i = 0; i < data.size(); i++) { f[i] = data.get(i); } return f; } 4.2 createBottomCirclePos() private float[] createBottomCirclePos(float radius, int n, float circleCenterZ) { ArrayList<Float> data = new ArrayList<>(); //顶部/底部圆心坐标 data.add(0.0f); data.add(0.0f); data.add(circleCenterZ); //设置顶部/底部圆的顶点坐标 float angDegSpan = 360f / n; for (float i = 0; i < 360 + angDegSpan; i += angDegSpan) { data.add((float) (radius * Math.sin(i * Math.PI / 180f))); data.add((float) (radius * Math.cos(i * Math.PI / 180f))); //顶部/底部圆的顶点Z坐标设置为-0.7f data.add(circleCenterZ); } //所有顶点坐标 float[] f = new float[data.size()]; for (int i = 0; i < data.size(); i++) { f[i] = data.get(i); } return f; } 五.GLRender:绘制 5.1 MVP矩阵 //填充MVP矩阵 mMVPMatrix = TransformUtils.getCylinderMVPMatrix(ratio); //将变换矩阵传入顶点渲染器 glUniformMatrix4fv(mvpMatrix, 1, false, mMVPMatrix, 0);getCylinderMVPMatrix():
public static float[] getCylinderMVPMatrix(float ratio) { float[] modelMatrix = getIdentityMatrix(16, 0); //模型变换矩阵 float[] viewMatrix = getIdentityMatrix(16, 0); //观测变换矩阵/相机矩阵 float[] projectionMatrix = getIdentityMatrix(16, 0); //投影变换矩阵 mConeRotateAgree = (mConeRotateAgree + 1) % 360; //旋转方向xyz三个轴是相对于相机观察方向的 Matrix.rotateM(modelMatrix, 0, mConeRotateAgree, 1, 0, 1); //获取模型旋转变换矩阵 //设置相机位置 Matrix.setLookAtM(viewMatrix, 0, 5, 0.0f, -3.0f, 0f, 0f, 0f, 0f, 0.0f, 1.0f); //设置透视投影 Matrix.frustumM(projectionMatrix, 0, -ratio, ratio, -1, 1, 3, 10); //计算变换矩阵 float[] tmpMatrix = new float[16]; Matrix.multiplyMM(tmpMatrix, 0, viewMatrix, 0, modelMatrix, 0); float[] mvpMatrix = new float[16]; Matrix.multiplyMM(mvpMatrix, 0, projectionMatrix, 0, tmpMatrix, 0); return mvpMatrix; } 5.2 绘制圆柱柱面、顶部圆、底部圆(1).drawSide()
//准备顶点坐标和颜色数据 glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, false, 0, vertexBuffer); //绘制 glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexData.length / 3);(2).drawBottomCircle1()
//准备顶点坐标和颜色数据 glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, false, 0, vertexBuffer1); //绘制 glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData1.length / 3);(3).drawBottomCircle2()
//准备顶点坐标和颜色数据 glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, false, 0, vertexBuffer2); //绘制 glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData2.length / 3); 六.着色器代码 6.1 cylinder_vertex_shader.glsl先实现一个顶部绿色,底部红色,柱面绿红渐变的旋转圆柱
#version 300 es layout (location = 0) in vec4 vPosition; layout (location = 1) in vec4 aColor; uniform mat4 mvpMatrix; out vec4 vColor; void main() { gl_Position = mvpMatrix * vPosition; if (vPosition.z == 0.7) { vColor = vec4(0.0, 1.0, 0.0, 0.0); //绿 } else if (vPosition.z == -0.7) { vColor = vec4(1.0, 0.0, 0.0, 0.0); //红 } } 6.2 cylinder_fragtment_shader.glsl #version 300 es #extension GL_OES_EGL_image_external_essl3 : require precision mediump float; in vec4 vColor; out vec4 outColor; void main(){ outColor = vColor; } 七.两种效果上一节中讲了,先来一个顶部绿,底部红,柱面绿红渐变的旋转3D圆柱
效果如下:
如何实现混色渐变的旋转圆柱呢?
很简单,只要修改顶点着色器代码:
void main() { gl_Position = mvpMatrix * vPosition; //颜色混合渐变 vColor = vec4(vPosition.x,vPosition.y, vPosition.z,0.0); }效果如下:
八.结束语两种混色旋转的3D圆柱绘制过程到此讲解结束
下一篇讲解混色旋转的圆锥
OpenGLES:绘制一个混色旋转的3D圆柱由讯客互联人工智能栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“OpenGLES:绘制一个混色旋转的3D圆柱”