OpenGLES:绘制一个混色旋转的3D圆锥

这篇具有很好参考价值的文章主要介绍了OpenGLES:绘制一个混色旋转的3D圆锥。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

效果展示:

本篇博文总共会实现两种混色旋转的3D圆锥:

OpenGLES:绘制一个混色旋转的3D圆锥,OpenGL/OpenGLES,3d,图像处理,计算机视觉,算法,图形渲染,androidOpenGLES:绘制一个混色旋转的3D圆锥,OpenGL/OpenGLES,3d,图像处理,计算机视觉,算法,图形渲染,android

一.圆锥解析

1.1 对圆锥的拆解

上一篇博文讲解了绘制圆柱体,这一篇讲解绘制一个彩色旋转的圆锥

在绘制圆柱体时提到过,关键点是先将圆柱进行拆解,便于创建出顶点坐标数组

同样,绘制圆锥也先进行拆解

圆锥的拆解很简单,有两种方式可以理解:

  • 2D圆的圆心从圆平面里抽离出来,赋予一个Z值
  • 2D的圆心和圆平面分别赋予不同的Z值

也就是把圆锥拆成:一个2D圆 + 扇形锥面

1.2 单位图元:三角形

讲到这里顺带提一句:

在OpenGL的世界里,不论多么复杂图形,最终都会被拆解成使用最基础的单位图元:三角形来完成绘制

为什么OpenGL渲染的基础单位图元是三角形呢?

因为一个点只是点,两个点组成线,三个点能确定一个面。

三角形是形成一个面最基础的图形单元,所以也是OpenGL的基础图元。

二.GLRender:变量定义

这次顶点颜色数组的定义和赋值与立方体绘制类似,在Render类中使用代码动态完成

2.1 常规变量定义

//MVP矩阵
private float[] mMVPMatrix = new float[16];

//着色器程序/渲染器
private int shaderProgram;

//mvp变换矩阵属性
private int mvpMatrixLoc;
//位置属性
private int aPositionLocation;
//颜色属性
private int aColorLocation;

//surface宽高比率
private float ratio;

2.2 定义顶点坐标数组和缓冲

//圆锥锥顶 顶点
private float vertexData[];
//圆锥底部圆 顶点
private float vertexData1[];
//圆锥锥顶 顶点颜色
private float colorData[];
//圆锥底部圆 顶点颜色
private float colorData1[];

//对应的坐标和颜色缓冲
private FloatBuffer vertexBuffer;
private FloatBuffer vertexBuffer1;
private FloatBuffer colorBuffer;
private FloatBuffer colorBuffer1;

2.3 定义MVP矩阵

//MVP矩阵
private float[] mMVPMatrix = new float[16];

三.GLRender:着色器、内存分配等

3.1 着色器创建、链接、使用

3.2 着色器属性获取、赋值

3.3 缓冲内存分配

这几个部分的代码实现2D图形绘制基本一致

可参考以前2D绘制的相关博文,里面都有详细的代码实现

不再重复展示代码

四.GLRender:动态创建顶点

需要传入两个参数:

  • 圆锥底部圆半径长度
  • 底部圆和圆锥扇面分割份数
createPositions(0.6f, 60);

函数实现:

private void createPositions(float radius, int n) {
	ArrayList<Float> red = new ArrayList<>();
	ArrayList<Float> blue = new ArrayList<>();
	ArrayList<Float> magenta = new ArrayList<>();
	ArrayList<Float> totalColor1 = new ArrayList<>();
	ArrayList<Float> totalColor2 = new ArrayList<>();
	//红
	red.add(1.0f);
	red.add(0.0f);
	red.add(0.0f);
	red.add(0.0f);
	//蓝
	blue.add(0.0f);
	blue.add(0.0f);
	blue.add(1.0f);
	blue.add(0.0f);
	//粉 Magenta
	magenta.add(1.0f);
	magenta.add(0.2f);
	magenta.add(1.0f);
	magenta.add(0.0f);

	ArrayList<Float> data = new ArrayList<>();
	//设置圆心的顶点坐标
	data.add(0.0f);
	data.add(0.0f);
	data.add(1.0f);
	//设置底部圆的顶点坐标
	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.5f
		data.add(-0.5f);
	}
	//所有顶点坐标
	float[] f = new float[data.size()];
	for (int i = 0; i < f.length; i++) {
		f[i] = data.get(i);
	}
	vertexData = f;

	//设置圆心和底部圆顶点对应的颜色数据
	colorData = new float[f.length * 4 / 3];
	for (int i = 0; i < f.length / 3; i++) {
		if (i == 0) {
			totalColor1.addAll(red);
		} else {
			totalColor1.addAll(blue);
		}
	}

	for (int i = 0; i < totalColor1.size(); i++) {
		colorData[i] = totalColor1.get(i);
	}

	//底部圆
	vertexData1 = new float[vertexData.length];
	for (int i = 0; i < vertexData.length; i++) {
		if (i == 2) {
			vertexData1[i] = -0.5f;
		} else {
			vertexData1[i] = vertexData[i];
		}
	}

	colorData1 = new float[f.length * 4 / 3];
	for (int i = 0; i < f.length / 3; i++) {
		totalColor2.addAll(magenta);
	}
	for (int i = 0; i < totalColor2.size(); i++) {
		colorData1[i] = totalColor2.get(i);
	}
}

五.GLRender:绘制

5.1 MVP矩阵

//MVP矩阵赋值
mMVPMatrix = TransformUtils.getConeMVPMatrix(ratio);
//将变换矩阵传入顶点渲染器
glUniformMatrix4fv(mvpMatrixLoc, 1, false, mMVPMatrix, 0);

getConeMVPMatrix():

采用的是透视投影方式

public static float[] getConeMVPMatrix(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 绘制圆锥的锥顶锥面、底部圆

drawCenterAndSide();
drawBottomCircle();

(1).drawCenterAndSide()

//准备顶点坐标和颜色数据
glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, false, 0, vertexBuffer);
glVertexAttribPointer(aColorLocation, 4, GL_FLOAT, false, 0, colorBuffer);

//绘制
glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData.length / 3);

(2).drawBottomCircle()

//准备顶点坐标和颜色数据
glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, false, 0, vertexBuffer1);
//底部圆颜色(粉色)缓冲
glVertexAttribPointer(aColorLocation, 4, GL_FLOAT, false, 0, colorBuffer1);

//绘制
glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData1.length / 3);

六.着色器代码

(1).cone_vertex_shader.glsl

#version 300 es

layout (location = 0) in vec4 vPosition;
layout (location = 1) in vec4 aColor;

uniform mat4 u_Matrix;

out vec4 vColor;

void main() {
    gl_Position  = u_Matrix*vPosition;
    vColor = aColor;
}

(2).cone_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;
}

七.两种效果

最终实现出来的是锥面红蓝渐变、锥底粉色的圆锥

OpenGLES:绘制一个混色旋转的3D圆锥,OpenGL/OpenGLES,3d,图像处理,计算机视觉,算法,图形渲染,android

个人这个效果并不太好,底部和锥面的颜色变化没有渐变,过于突兀 

只要在绘制底部圆的函数中更改一下,就可以得到底部圆心对应锥顶颜色,圆周对应锥面底部颜色的圆锥

注释掉底部圆的颜色缓冲代码

//准备顶点坐标和颜色数据
glVertexAttribPointer(aPositionLocation, 3, GL_FLOAT, false, 0, vertexBuffer1);
//注释掉这句,底部圆的圆心颜色就会和圆锥锥顶颜色一样,底部圆的圆周颜色和圆锥锥面底部颜色一样
//glVertexAttribPointer(aColorLocation, 4, GL_FLOAT, false, 0, colorBuffer1);

//绘制
glDrawArrays(GL_TRIANGLE_FAN, 0, vertexData1.length / 3);

效果如下:

OpenGLES:绘制一个混色旋转的3D圆锥,OpenGL/OpenGLES,3d,图像处理,计算机视觉,算法,图形渲染,android

八.结束语

两种混色旋转的3D圆锥绘制过程到此讲解结束

下一篇博文讲解混色旋转的3D球体绘制文章来源地址https://www.toymoban.com/news/detail-715707.html

到了这里,关于OpenGLES:绘制一个混色旋转的3D圆锥的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • matplotlib 齐次坐标系 绘制旋转 3D 立体

    齐次坐标系描述了刚体的坐标系、位置,而且还提供了一套相对旋转、相对移动、绝对旋转、绝对移动的方法,用来绘制旋转的 3D 立体是再好不过的选择 将笛卡尔坐标系的三个轴记为 ,将任意的齐次坐标系记为 我们使用这样一个矩阵来描述 坐标系与 坐标系之间的关系:

    2024年02月09日
    浏览(41)
  • OPenGL笔记--创建一个3D场景

    通过前面的学习,基本掌握了怎么绘制图形,使用纹理,接下来就来创建一个3D场景。 基本原理 一个复杂的场景肯定是由一些简单的图形,通过某种组合方式构建起来的,在OPenGL中也不例外;例如:在绘制立方体的时候,立方体也是由6个正方形围起来的; 基本图形 由于显卡

    2024年02月11日
    浏览(41)
  • Direct3D绘制旋转立方体例程

    初始化文件见Direct3D的初始化_direct3dcreate9_寂寂寂寂寂蝶丶的博客-CSDN博客 D3DPractice.cpp 运行结果

    2024年02月09日
    浏览(44)
  • Qt3D绘制旋转立方体

    近期用了款叫DesktopSpace,也想实现一下这款软件实现的效果 具体实现步骤: 使用Qt3D绘制个旋转的立方体(一) 使用快捷键控制立方体显示面(二) 创建6个人虚拟桌面,截取不同虚拟桌面,显示在不同的面上 (三) 在立方体上播放视频 首先用Qt3D绘制一下桌面截图旋转的效

    2024年02月06日
    浏览(48)
  • [Python从零到壹] 七十二.图像识别及经典案例篇之OpenGL入门及绘制基本图形和3D图

    十月太忙,还是写一篇吧!祝大家1024节日快乐O(∩_∩)O 欢迎大家来到“Python从零到壹”,在这里我将分享约200篇Python系列文章,带大家一起去学习和玩耍,看看Python这个有趣的世界。所有文章都将结合案例、代码和作者的经验讲解,真心想把自己近十年的编程经验分享给大家

    2024年02月06日
    浏览(58)
  • 如何用css实现一个3D旋转照片墙

       学习前端是件很有趣的事,今天我又来分享一下关于html+css实现的3D效果的照片墙的代码啦,希望感兴趣的小伙伴会喜欢!    今天,我们要做一个3D旋转相册,首先让我们了解一下关于3D。    3D立体其实就像数学中的x轴,y轴,z轴,在网页上设置z轴与y轴的偏移量,能给

    2024年02月01日
    浏览(54)
  • pycharm中绘制一个3D曲线

    运行后结果如下:

    2024年02月04日
    浏览(46)
  • JavaScript+canvas实现一个旋转的3D球动画效果

    1. 获取Canvas元素和设置初始参数 这部分代码主要是获取Canvas元素,并根据设备的DPI进行缩放。然后,定义了一些全局变量,包括Canvas的宽度、高度、球体旋转的角度和存储所有点的数组。 2. 定义一些常量 这部分代码定义了一些常量,如点的数量、点的半径、球半径等。 3.定

    2024年01月18日
    浏览(57)
  • 计算机图形学:绘制一个3d交互场景(1)

    OpenGL作为一种图形与硬件的接口,与其他图形程序开发工具相比较,它提供了众多图形函数,直观的编程环境简化了三维图形的绘制过程,使用OpenGL搭建一个三维场景,能够通过输入设备与场景内物体交互。 豪华单间 配置环境:vs22+freeglut库 1.绘制墙体使其成为封闭空间,在

    2024年02月11日
    浏览(108)
  • OpenGLES:3D立方体纹理贴图

    前几篇博文讲解了OpenGLES绘制多种3D图形,并赋予丰富的色彩,但是在这些3D图形绘制过程中,有一点还没有涉及,就是 纹理贴图。 今天这篇博文我会用如下 六张图片 对立方体进行纹理贴图,实现 六个面都是贴图 的3D旋转立方体 2.1 常规变量定义 2.2 顶点、纹理相关变量定义

    2024年02月08日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包