OpenGL-ES 学习(14) ----顶点指定和基本图元的绘制

目录

本节概述

绘制图形的第一步就是指定顶点坐标,可以每个顶点指定,也可以是用于所有顶点的常量,或者直接用顶点数组指定,OpenGL-ES 标准实现必须支持最少 16 个顶点属性;

顶点着色器处理图元顶点之后进入图元装配阶段,在这个阶段执行裁剪,透视分割和视口变换 ,往后会进入光栅化阶段;
光栅化是指将图元转换为一组二维片段的过程,这些片段最后会由FragmentShader 处理

顶点的指定

常量顶点属性和顶点数组

常量顶点属性对一个图元的所有顶点都相同,所以对图元的所有顶点都只需要指定一个值,可以用下面的函数指定:

顶点指定函数 说明
glVertexAttrib1f 加载顶点 (x,0.0,0.0,1.0)
glVertexAttrib2f 加载顶点 (x,y,0.0,1.0)
glVertexAttrib3f 加载顶点 (x,y,z,1.0)
glVertexAttrib4f 加载顶点 (x,y,z,w)
glVertexAttrib1fv 加载顶点 (x,0.0,0.0,1.0)
glVertexAttrib2fv 加载顶点 (x,y,0.0,1.0)
glVertexAttrib3fv 加载顶点 (x,y,z,1.0)
glVertexAttrib4fv 加载顶点 (x,y,z,w)

常量顶点属性提供标量/向量等价的功能

顶点数组

顶点数组指定每个顶点的属性,是保存在应用程序地址空间的缓冲区,使用下面的函数指定

函数 说明
glVertexAttribPointer 指定顶点数组
glVertexAttribIPointer 指定顶点数组

glVertexAttribPointer (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsize stride, const void *pointer)

  • GLuint index 指定通用顶点属性索引,从0到 最大支持索引数 -1
  • GLint size 所指定的分类数量 有效值 1~4
  • GLenum type 数据格式
  • GLboolean normalized 表示非浮点类型在转换为浮点数时是否应该规范化
  • GLsize stride 表示两个顶点之间的位移,如果stride 为 0,表示按照顺序存储
  • const void *pointer 顶点数据缓冲区的指针

重点关注的是

  • GLuint index : 和Shader 中的指定的 layout 一致
  • void *pointer : 指向顶点的指针
顶点属性的定义

定义顶点属性的坐标并且关联到一个属性索引上,

对应的代码:

c 复制代码
GLfloat color[4] = { 1.0f, 0.0f, 0.0f, 1.0f };
// 3 vertices, with (x,y,z) per-vertex
GLfloat vertexPos[3 * 3] = {
   0.0f,  0.5f, 0.0f, // v0
   -0.5f, -0.5f, 0.0f, // v1
   0.5f, -0.5f, 0.0f  // v2
};
glViewport ( 0, 0, esContext->width, esContext->height );
glClear ( GL_COLOR_BUFFER_BIT );
glUseProgram ( userData->programObject );

//注意下面的顶点定义方式
glVertexAttribPointer ( 0, 3, GL_FLOAT, GL_FALSE, 0, vertexPos );
glEnableVertexAttribArray ( 0 );
//常量的顶点属性,表示每个顶点的 color 都是上面定义的
glVertexAttrib4fv ( 1, color );

glDrawArrays ( GL_TRIANGLES, 0, 3 );
glDisableVertexAttribArray ( 0 );
Shader 中声明顶点属性变量

VertexShader 中,使用 in 限定符声明为顶点属性,顶点属性变量也可以包含一个布局限定符,提供属性索引,示例如下:
layout(location = 0) in vec4 a_position
layout(location = 1) in vec2 a_texcoord
layout(location = 2) in vec3 a_normal

属性变量不能声明为数组或者结构,在 Vertex Shader 中定义的顶点属性是只读变量 ,不能修改
OpenGL-ES3.0 实现支持 GL_MAX_VERTEX_ATTRIBS 四分量向量顶点属性,声明为标量,二分量,三分量, 的顶点属性都会被当做一个四分量向量属性计算;

与编译器进行自动打包的统一变量和 Vertex Shader Input/outout 不同,属性不进行打包

查询当前活动顶点的数量的函数:
glGetActiveAttrib

顶点属性的绑定

通过通用属性索引的方法映射到 Vertex Shader 中声明的对应属性变量 ;这种映射使对应的顶点数据可以读入Vertex Shader 中正确的属性变量;

可以使用下面三种方法将通用顶点属性映射到Vertex Shader 中:

  • 索引在 Vertex Shader 源码中用 layout 指定
  • OpenGL-ES 3.0 将通用顶点属性索引绑定到属性名称
  • 应用程序可以将顶点属性索引绑定到属性名称

第一种方法最简单,但是某些时候,第二,三种方法更合适,使用下面的函数实现:
glBindAttribLocation (GLuint program, GLuint index, const GLchar 、*name);

直接将索引绑定到 Vertex Shader 的属性变量上

基本图元绘制

基本图元

OpenGL-ES 可以绘制三角形、直线、点这个三种基本图元

三角形

三角形的主要类型有 GL_TRIANGLESGL_TRIANGLES_STRIPGL_TRIANGLE_FAN

GL_TRIANGLES 绘制一系列单独三角形,总共绘制 n/3 个三角形
GL_TRIANGLES_STRIP 绘制一系列相互连接的三角形,总共绘制 n-2 个三角形
GL_TRIANGLES_FAN 总共绘制 n-2 个三角形

直线

直线图元类型有 GL_LINESGL_LINES_STRIPGL_LINES_LOOP

GL_LINES:绘制一系列类不相连的线段,总共绘制n/2条线段
GL_LINES_STRIP:绘制一系列相连的线段,总共绘制n-1条线段
GL_LINES_LOOP:和GL_LINES_STRIP类型总共绘制n条线段

绘制图元的API

OpenGL ES 中绘制基本图元共有5个API

OpenGL-ES API 说明
glDrawArrays 常用
glDrawElements 常用
glDrawRangeElements 常用
glDrawArraysInstanced NA
glDrawElementsInstanced NA

void glDrawArrays( GLenum mode, GLint first, GLsizei count);
mode: 要绘制的图元类型
first:顶点数组中的顶点数组索引(顶点位置数组的偏移量)
count: 指定要绘制的顶点数量,如果选择 GL_TRIANGLES,那么顺次每三个顶点构成一个三角形

注意第二个值 fist,表示在顶点数组中的位置

void glDrawElements( GLenum mode, GLsizei count, GLenum type,const void * indices);

void glDrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsizei count,GLenum type, const void * indices)

mode: 要绘制的图元类型
start:顶点数组中的最小数组索引(仅glDrawRangeElements)
end:顶点数组中的最大数组索引(仅glDrawRangeElements)

count: 要绘制的顶点数量,如果如果选择GL_TRIANGLES,那么顺次每三个顶点构成一个三角形

type: 指定 indices(下面一个参数)中保存的元素索引类型,有效值为:

  • GL_UNSIGNED_BYTE
  • GL_UNSIGNED_SHORT
  • GL_UNSIGNED_INT
    indices: 指向一段存储区,缓存在顶点数组中顶点的偏移
    比如下面
c 复制代码
GLfloat vVertices[] = { -0.5f,  0.5f, 0.0f,  // Position 0
	0.0f,  0.0f,        // TexCoord 0 
	-0.5f, -0.5f, 0.0f,  // Position 1
	0.0f,  1.0f,        // TexCoord 1
	0.5f, -0.5f, 0.0f,  // Position 2
	1.0f,  1.0f,        // TexCoord 2
	0.5f,  0.5f, 0.0f,  // Position 3
	1.0f,  0.0f         // TexCoord 3
};
GLushort indices[] = { 0, 1, 2, 0, 2, 3 };
glDrawElements(GL_TRIANGLES, 3, GL_UNSIGNED_SHORT, indices);

这里的 indices 就分辨表示上面 vVertices 顶点,顶点0,1,2构成一个三角形,顶点0,2,3构成一个三角形

c 复制代码
static void Draw(ESContext *esContext)
{
	UserData *userData = esContext->userData;
	//R G B A
	GLfloat color[4] = { 1.0f, 1.0f, 0.0f, 1.0f };
	// 3 vertices, with (x,y,z) per-vertex
	//绘制一个六边形 共六个顶点
	GLfloat vertexPos[6*3*3] =
	{
		1.0f,  0.0f, 0.0f, 
		0.5f,  1.0f, 0.0f,
		0.0f,  0.0f, 0.0f,

		-0.5f,  1.0f, 0.0f,
		0.5f,  1.0f, 0.0f,
		0.0f,  0.0f, 0.0f,

		-0.5f,  1.0f, 0.0f,
		-1.0f,  0.0f, 0.0f,
		0.0f,  0.0f, 0.0f,

		-1.0f,  0.0f, 0.0f,
		-0.5f,  -1.0f, 0.0f,
		0.0f,  0.0f, 0.0f,

		-0.5f,  -1.0f, 0.0f,
		0.5f,  -1.0f, 0.0f,
		0.0f,  0.0f, 0.0f,


		0.5f,  -1.0f, 0.0f,
		1.0f,  0.0f, 0.0f,
		0.0f,  0.0f, 0.0f,
	};

	glViewport(0, 0, esContext->width, esContext->height);

	glClear(GL_COLOR_BUFFER_BIT);
	glUseProgram(userData->programObject);

	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertexPos);
	glEnableVertexAttribArray(0);
	glVertexAttrib4fv(1, color);

	for (int i = 0; i < 3 * 2; i++) {
		glDrawArrays(GL_TRIANGLES, i*3, 3);
	}

	//作用和上面的循环是一致的
	/*glDrawArrays(GL_TRIANGLES, 0, 3*6);*/
	glDisableVertexAttribArray(0);
}
相关推荐
西岸行者5 天前
学习笔记:SKILLS 能帮助更好的vibe coding
笔记·学习
悠哉悠哉愿意5 天前
【单片机学习笔记】串口、超声波、NE555的同时使用
笔记·单片机·学习
别催小唐敲代码5 天前
嵌入式学习路线
学习
毛小茛5 天前
计算机系统概论——校验码
学习
babe小鑫5 天前
大专经济信息管理专业学习数据分析的必要性
学习·数据挖掘·数据分析
winfreedoms5 天前
ROS2知识大白话
笔记·学习·ros2
在这habit之下5 天前
Linux Virtual Server(LVS)学习总结
linux·学习·lvs
我想我不够好。5 天前
2026.2.25监控学习
学习
im_AMBER5 天前
Leetcode 127 删除有序数组中的重复项 | 删除有序数组中的重复项 II
数据结构·学习·算法·leetcode
CodeJourney_J5 天前
从“Hello World“ 开始 C++
c语言·c++·学习