如何在OpenGL中获取GPU使用率

如何在OpenGL中获取GPU使用率,第1张

opengl 和dx 没有标准语句去获得这种效率的参数 只能是使用显卡厂商提供的调试工具 一般显卡厂商都有自己的工具套件 比如nvidia有个叫什么 performance HUD 的东西可以看当前显卡使用率这你要到显卡厂商的下载页面去找啦

从“相对移动”的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性。在OpenGL中,实现这两种功能甚至使用的是同样的函数。

由于模型和视图的变换都通过矩阵运算来实现,在进行变换前,应先设置当前 *** 作的矩阵为“模型视图矩阵”。设置的方法是以GL_MODELVIEW为参数调用glMatrixMode函数,像这样:

glMatrixMode(GL_MODELVIEW);

通常,我们需要在进行变换前把当前矩阵设置为单位矩阵。这也只需要一行代码:

glLoadIdentity();

然后,就可以进行模型变换和视图变换了。进行模型和视图变换,主要涉及到三个函数:

glTranslate,把当前矩阵和一个表示移动物体的矩阵相乘。三个参数分别表示了在三个坐标上的位移值。

glRotate,把当前矩阵和一个表示旋转物体的矩阵相乘。物体将绕着(0,0,0)到(x,y,z)的直线以逆时针旋转,参数angle表示旋转的角度。

glScale,把当前矩阵和一个表示缩放物体的矩阵相乘。x,y,z分别表示在该方向上的缩放比例。

注意我都是说“与XX相乘”,而不是直接说“这个函数就是旋转”或者“这个函数就是移动”,这是有原因的,马上就会讲到。

假设当前矩阵为单位矩阵,然后先乘以一个表示旋转的矩阵R,再乘以一个表示移动的矩阵T,最后得到的矩阵再乘上每一个顶点的坐标矩阵v。所以,经过变换得到的顶点坐标就是((RT)v)。由于矩阵乘法的结合率,((RT)v) = (R(Tv)),换句话说,实际上是先进行移动,然后进行旋转。即:实际变换的顺序与代码中写的顺序是相反的。由于“先移动后旋转”和“先旋转后移动”得到的结果很可能不同,初学的时候需要特别注意这一点。

OpenGL之所以这样设计,是为了得到更高的效率。但在绘制复杂的三维图形时,如果每次都去考虑如何把变换倒过来,也是很痛苦的事情。这里介绍另一种思路,可以让代码看起来更自然(写出的代码其实完全一样,只是考虑问题时用的方法不同了)。

让我们想象,坐标并不是固定不变的。旋转的时候,坐标系统随着物体旋转。移动的时候,坐标系统随着物体移动。如此一来,就不需要考虑代码的顺序反转的问题了。

以上都是针对改变物体的位置和方向来介绍的。如果要改变观察点的位置,除了配合使用glRotate和glTranslate函数以外,还可以使用这个函数:gluLookAt。它的参数比较多,前三个参数表示了观察点的位置,中间三个参数表示了观察目标的位置,最后三个参数代表从(0,0,0)到 (x,y,z)的直线,它表示了观察者认为的“上”方向。

OpenGL中的物体、世界、照相机坐标系都属于右手坐标系,而规范化设备坐标系使用左手坐标系。

OpenGL每次顶点着色后,我们的可见顶点都为规范化设备坐标(Normalized Device Coordinate,NDC)。也就是说每个顶点的x,y,z都应该在-1到1之间,超过这个范围的顶点将是不可见的。

通常情况下我们会自己设定一个坐标范围,之后再在顶点着色器中将这些坐标转化为规范化设备坐标。然后把规范化设备坐标传入光栅器(Rasterizer),将它们变换为屏幕上的二维坐标和像素。

将坐标变换为规范化设备坐标,接着再转化为屏幕坐标的过程通常是分步进行的,类似于流水线那样子。在流水线中,物体的顶点最终转化为屏幕坐标之前还会被变换到多个坐标系统(Coordinate System)。将物体的坐标变换到几个过渡坐标系统(Intermediate Coordinate System)的优点在于,在这些特定的坐标系统中,一些 *** 作或运算更加方便和容易,这一点很快就会变得很明显。对我们来说比较重要的总共有5个不同的坐标系统:

就是一个顶点在最终被转化为片元之前需要经历的所有不同状态。为了将坐标从一个坐标系变换到另一个坐标系,我们需要用到几个变换矩阵,最重要的几个分别是模型(Model)、观察(View)、投影(Projection)三个矩阵。物体顶点的起始坐标在局部空间(Local Space),这里称它为局部坐标(Local Coordinate),它在之后会变成世界坐标(World Coordinate),观测坐标(View Coordinate),裁剪坐标(Clip Coordinate),并最后以屏幕坐标(Screen Coordinate)的形式结束。

在3D图形学中常用的坐标系:

世界坐标系:世界坐标系是系统的绝对坐标系,在没有建立用户坐标系之前画面上所有的点的坐标都可以在该坐标系的原点来确定自己的位置,世界坐标系始终是固定不变的。

物体坐标系:每个物体都有它们独立的坐标系,当物理移动或改变方向时,该物体相关联的坐标系将随之移动或改变方向。

物体坐标系是以物体本身而言,比如,我向你发指令“向前走一步”,是向你的物体坐标系指令。我并不知道你会向哪个绝对的方向移动。比如说,当你开车时,有人会说向左转,有人说向东。但是,向左转是物体坐标系的概念,而向东则是世界坐标系中的。

在某种情况下,我们可以理解物体坐标系为模型坐标系。因为模型顶点的坐标都是在模型坐标系中描述的。

惯性坐标系:指的是世界坐标系到物体坐标系的“半途”。惯性坐标系的原点和物体坐标系的原点重合,但惯性坐标系的轴平行于世界坐标系的轴。

OpenGL然后对裁剪坐标执行透视除法从而将它们变换到标准化设备坐标。OpenGL会使用 glViewPort 内部的参数将标准化设备坐标映射到屏幕坐标,每个坐标都关联了屏幕上的一个点,这个过程称为视口变换。

局部坐标系(模型坐标系)是为了方便构造模型而设立的坐标系,建立模型时我们无需关心最终对象显示在屏幕哪个位置。模型变换的主要目的是通过变换使得用顶点属性定义或者3d建模软件构造的模型,能够按照需要,通过缩小、平移等 *** 作放置到场景中合适的位置。通过模型变换后,物体放置在一个全局的世界坐标系中,世界坐标系是所有物体交互的一个公共坐标系。

点的属性恐怕就只有点的大小了,通过调用 void glPointSize(GLfloat size) 函数可以设置点的大小,传入的参数是一个浮点数代表点的像素。

这个设置是支持 反走样 (antialiasing)的,如果你设置了反走样这个函数同样适用。

线的属性大致有两种,一是线宽,二是样式。

设置线宽和设置点大小一样,通过 void glLineWidth(GLfloat width) 函数来设置,传入的参数也是浮点数。同样支持反走样。

线的样式设置比较有意思,通过 void glLineStipple(GLint factor,GLushort pattern) 函数来设置。第一个参数是因子,我把它简单的理解为线条样式拉伸的系数,第二个参数比较有趣,它是用来描绘具体样式的16位整数。1对应实线,0对应空白,通过这种方法表现出来样式。

这是我画的虚线,对应的样式是0x0A0A。在设置样式的时候需要调用 glEnable(GL_LINE_STIPPLE) 函数打开线段样式渲染状态。

即使是二维的平面也分为正面和背面,比如说如果我顺时针方向渲染的点为正面,那么逆时针渲染的点就是背面了。有了这一概念我们就可以单独的对图形的某一个面 *** 作,比如说正面填充背面描边。

void glFrontFace(GLenum mode) 可以设置图形的正面与背面(相反的为背面),参数是顺时针或逆时针。 void glPolygonMode(GLenum face,GLenum mode) 可以分别对正面或背面以不同方式渲染。举个例子。

我通过顺时针和逆时针两种方式画的两个三角形,渲染结果是不同的。

此外, void glEdgeFlag( GLboolean flag) 函数可以指定边是否是边界,如果不是可以隐藏它。

通过这个特性我简单的画了一个“二”。

关于面的属性还有很多。比如样式、纹理甚至雾化效果,这个在现代OpenGL里面再说吧。

1,OpenGL是一个状态机,当前设定某个状态之后,效果将一直持续到下次重新设定。状态可以查询。

2,关于变换(矩阵):

i)变换矩阵分为三类,其一是“模型视图”矩阵,其二是“投影”矩阵,其三是“纹理”矩阵;不同命令形成的矩阵将自动归到不同类别,例如glRotatef生成的矩阵属于模型视图,gluPerspective生产的矩阵自动归到投影矩阵那类。但是当你要glLoadIdentity时,你发现它无法自动归类,再或者说你要使用glMultMatrixf时,它也不知道归到哪一类时,这时你必须用命令glMatrixMode来指明清楚,让他归到哪一类。其实说是说三类,实际上当前矩阵就三个(设为M,P,T),假设现在又新生成一个模型视图矩阵A,那么实际上就是在当前的模型视图矩阵M后面再乘以M,即更新后的模型视图矩阵是MA,都是右边乘上去。

ii)关于变换顺序的理解:如果要在全局坐标系中理解,那么变换得反着看;如果想象成局部坐标系,那么变换就是顺着看(非归一化的缩放除外);

iii)关于矩阵堆栈,有一点必须要明白,那就是当前矩阵总是在栈顶的,也可以说,栈顶就是存放当前矩阵的地方。和i)类似,有三个堆栈(堆栈深度分别为32,2,2),分别用于存取三类矩阵。假设当前三个矩阵为(M,P,T),首先得通过glMatrixMode来指明清楚你即将使用哪个堆栈,如果用的是GL_MODELVIEW参数,然后再glPushMatrix时,就把当前的模型视图矩阵M复制一个(也就是把modelview栈的栈顶复制一个),然后压进了栈顶端(原来的栈顶成了现在的第二了,当然,现在栈顶和第二两个矩阵都是一样的,这样就起到保存当前设置的作用,因为接下来当前矩阵的改变实质是改变栈顶,第二及其以下都是不动的,除非使用pop后),假设你现在手头控制的模型视图矩阵还是M,假设现在又新生成一个模型视图矩阵A,那么当前的模型视图矩阵就是是MA,同时栈顶端的矩阵也是MA(因为栈顶就是当前矩阵),此时如果glPopMatrix的话(栈顶自己丢掉,第二个矩阵成栈顶了,因为栈顶就是当前,所以),那么当前的模型视图矩阵又成了M,因为栈顶是M,取出来之后作为当前的视图模型矩阵。 最后,由于深度有限,尽量少push,以免出错。

图像存储空间 = 图像的高度 图像宽度 每个像素的字节数

RGB(8位),宽度:199像素点。每行需要多少存储空间?

199 3 8 = 597字节

tga(纹理文件)。1个字节1个字节。

OpenGL纹理文件:tga文件

OpenGL ES! 压缩文件png/jpeg压缩

当纹理来使用。

//改变像素存储方式

void glPixelStorei(GLenum pname, GLint param);

//恢复像素存储方式

void glPixelStoref(GLenum pname,GLfloat param);

//举例:

//参数1:GL_UNPACK_ALTGNMENT 指定OpenGL 如何从数据缓存区中解包图像数据

//参数2:表示参数GL_UNPACK_ALIGNMENT 设置的值

//GL_UNPACK_ALIGNMENT 指内存中每个像素行起点的排列请求,允许设置为1(byte排列)、2(排列为偶数btye的行)、4(字word排列)、8(行从双字节边界开始)

glPixelStorei(GL_UNPACK_ALIGNMENT,1);

参数1:x,矩形左下角的窗口坐标

参数2:y,矩形左下角的窗口坐标

参数3:width,矩形的宽,以像素为单位

参数4:height,矩形的高,以像素为单位

参数5:format,OpenGL的像素格式

参数6:type,解释参数pixels指向的数据,告诉OpenGL 使用缓存区中的什么数据类型来存储颜色分量,像素数据的数据类型。

参数7:pixels,指向图形数据的指针

void glReadPixls(GLint x, GLint y, GLSizei width, GLSizei height, GLenum format, GLenum type, const void pixels);

glReadBuffer(mode); ->指定读取的缓存

glWriteBuffer(mode); -> 指定写入的缓存

void glTexImage1D(GLenum target,GLint level, GLint internalformat,GLsizei width, GLint border, GLenum format, GLenum type, void data);

void glTextImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint bordr, GLenum format, GLenum type,void data);

void glTextImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,GLsizei depth, GLint bordr, GLenum format, GLenum type,void data);

void glTexSubImage1D(GLenum target, GLint level, GLint xOffset, GLsizei width, GLenum format, GLenum type, const GLvoid data);

void glTexSubImage2D(GLenum target, GLint level, GLint xOffset,GLint yOffset,GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid data);

void glTexSubImage3D(GLenum target, GLint level, GLint xOffset,GLint yOffset,GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid data);

void glCopyTexSubImage1D(GLenum target, GLint level, GLint xOffset, GLint x, GLint y, GLsizei width);

void glCopyTexSubImage2D(GLenum target,GLint level,GLint xOffset, GLint yOffset,GLint x, GLint y,GLsizei width, GLsizei height);

void glCopyTexSubImage3D(GLenum target, GLint level, GLint xOffset, GLint yOffset, GLint zOffset, GLint x, GLint y, GLsizei width, GLsizei height);

void glCopyTexImage1D(GLenum target, GLint level, GLenum internalformt, GLint x, GLint y, GLsizei width, GLint border);

void glCopyTexImage2D(GLenum target, GLint level, GLenum internalformt, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);

x,y在颜色缓存区中指定了开始读取纹理数据的位置;缓存区里的数据,是源缓存区通过glReadBuffer设置的。

//使用函数分配纹理对象

//指定纹理对象的数量 和 指针(指针指向一个屋符号整形数组,由纹理对象标识符填充)。

void glGenTextures(GLsizei n, GLint texTures);

//绑定纹理状态

//参数target: GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D

//参数texture:需要绑定的纹理对象

void glBindTexture(GLenum target, GLunit texture);

//删除绑定纹理对象

//纹理对象 以及 纹理对象指针(指针指向一个无符号整形数组,由纹理对象标识符填充)。

void glDeleteTexture(GLsizei n, GLint textures);

//测试纹理对象是否有效

//如果texture是一个已经分配空间的纹理对象。那么这个函数会返回GL_TRUE,否则返回GL_FALSE

GLboolean glIsTexture(GLuint texture);

glTexParameterf(GLenum target, GLenum pname, GLFloat param);

glTexParameteri(GLenum target, GLenum pname, GLint param);

glTexParameterfv(GLenum target, GLenum pname,GLint param);

glTexParameteriv(GLenum target, GLenum pname, GLint param);

参数1:target,指定这些参数将要应用在那个纹理模式上,比如GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D。

参数2:pname,指定需要设置那个纹理参数。

参数3:param,设定特定的纹理参数值。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,GL_NEAREST);

//纹理缩小时,使用邻近过滤

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GLLINEAR)

//纹理放大时,使用线性过滤

参数1:GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D

参数2:GL_TEXTURE_WRAP_S、GL_TEXTURE_T、GL_TEXTURE_R,针对s,t,r坐标

参数3:GL_REPEAT、GL_CLAMP、GL_CLAMP_TO_EDGE、GL_CLAMP_TO_BORDER

GL_REPEAT:OpenGL在纹理坐标超过10的方向上对纹理进行重复;

GL_CLAMP:所需要的纹理单元取自纹理边界或TEXTURE_BORDER_COLOR

GL_CLAMP_TO_EDGE环绕模式强制对范围之外的纹理坐标沿着合法的纹理单元的最后一行或者最后一列来进行采样。

GL_CLAMP_TO_BORDER:在纹理坐标在00到10范围之外的只使用边界纹理单元。边界纹理单元是作为围绕基本图像的额外的行和列,并与基本纹理图像一起加载的。

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAR_S,GL_CLAMP_TO_EDGE);

glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAR_T,GL_CLAMP_TO_EDGE);

OpenGL像素格式

像素数据的数据类型

//设置mip贴图基层

glTexParamteri(GL_TEXTURE_2D,GL_TEXTURE_BASE_LEVEL,0);

//设置mip贴图最大层

glTexParamteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_LEVEL,0);

GLint comFlag;

//判断纹理是否被成功压缩

glGetTexLevelParameteriv(GL_TEXTURE_2D,0,GL_TEXTURE_COMPRESSED,&comFlag);

//根据选择的压缩纹理格式,选择最快、最优、自行选择的算法方式选择压缩格式

glHint(GL_TEXTURE_COMPRESSION_HINT,GL_FASTEST);

glHint(GL_TEXTURE_COMPRESSION_HINT,GL_NICEST);

glHint(GL_TEXTURE_COMPRESSION_HINT,GL_DONT_CARE);

void glCompressedTexImage1D(GLenum target,GLint level,Glenum internalFormat,GLsizei width,GLint border, GLsizei imageSize, void data);

void glCompressedTexImage2D(GLenum target,GLint level, GLenum internalFormat, GLsizei width, GLint height, GLint border, GLsizei imageSize, void data);

void glCompressedTextImage3D(GLenum target, Glint level, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,GLint border, GLsizei imageSize,void data);

target: GL_TEXTURE_1D、GL_TEXTURE_2D、GL_TEXTURE_3D

level:指定所加载的mip贴图层次。一般我们都把这个参数设置为0

internalformat:每个纹理单元中存储多少颜色成分

width、height、depth参数:指加载纹理底层的宽度、高度、深度。注意:这些值必须是2的整数次方。(这是因为旧版本上遗留下的一个要求。当然现在已经可以支持不是2的整数次方。但是开发者还是习惯使用2的整数次方去设置参数)

border参数:允许为纹理贴图指定一个边界宽度。

format、type、data参数:与我们在讲glDrawPixels函数对应的参数相同

GLfloat mat[16];

glGetFloatv(GL_MODELVIEW_MATRIX, mat);

GL_MODELVIEW_MATRIX表示获取的是模型视图矩阵

以上就是关于如何在OpenGL中获取GPU使用率全部的内容,包括:如何在OpenGL中获取GPU使用率、opengl如何获取到变换的最终矩阵、OpenGL下坐标系统解析等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/9682597.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-04-30
下一篇 2023-04-30

发表评论

登录后才能评论

评论列表(0条)

保存