Opengles2.0怎样通过其自身的深度bytebufferr中获取深度值

pbuffer跟framebuffer功能是一样的,都是用来做渲染到一个off-screen surface上的,
但是如果要做的是渲染到一个纹理上,还是使用framebuffer,效率高些。
pbuffer的用途是:渲染到纹理上,随后这个纹理可以给其他API用的,比如openVG。
创建pbuffer的过程跟创建窗口surface差不多的:
&& &EGLSurface eglCreatePbufferSurface(EGLDisplay display,
&& &&& &EGLConfig config,
&& &&& &const EGLint *attribList);
&& &需要在attribList指定一些pbuffer的属性。
&& &选择config的时候需要指定:EGL_SURFACE_TYPE:EGL_PBUFFER_BIT
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:42351次
排名:千里之外
原创:49篇
转载:15篇
(1)(1)(11)(7)(8)(4)(2)(14)(1)(11)(4)3812人阅读
楼主收到这样的任务,在Android上用OpenGLES来显示YUV图像,之所以这样做,是因为:
1.Android本身也不能直接显示YUV图像,YUV转成RGB还是必要的;
2.YUV手动转RGB会占用大量的CPU资源,如果以这样的形式播放视频,手机会很热,所以我们尽量让GPU来做这件事;
3.OpenGLES是Android集成到自身框架里的第三方库,它有很多的可取之处。
博主的C/C++不是很好,所以整个过程是在Java层实现的,大家见笑,我主要参考(但不限于)以下文章,十分感谢这些朋友的分享:
1. http://blog.csdn.net/xiaoguaihai/article/details/8672631
2.http://chenshun87./blog/static//
3.http://blog.csdn.net/ypist/article/details/8950903
4.http://blog.csdn.net/wanglang3081/article/details/8480281
5.http://blog.csdn.net/xdljf/article/details/7178620
一、首先我先说一下这个解决方案是怎么运行的,给大家一个概念
1.显示在哪 -& GLSurfaceVIew
2.谁来把数据贴到GLSurfaceVIew上 -& Renderer
3.谁来负责YUV数据转换成RGB -& GL中的Program/Shader
一句话说明白就是:GL的Program/Shader把用户传过来的YUV数据,转换成RGB数据后,通过Renderer贴在GLSurfaceView上。
二、怎么检查你的手机是不是支持GLES2.0呢,使用下面的代码段就行了:
public static boolean detectOpenGLES20(Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
ConfigurationInfo info = am.getDeviceConfigurationInfo();
return (info.reqGlEsVersion &= 0x20000);
}一般的手机,都是会支持GLES2.0的,大家不必担心。
A 先要有一个GLSurfaceView,把它放入你的布局中就好了。
找到这个家伙,对它进行简单的设置,并为它设置一个Renderer。
Renderer的作用就是在GLSurfaceView上画出图像。
mGLSurface = (GLFrameSurface) findViewById(R.id.glsurface);
mGLSurface.setEGLContextClientVersion(2);
mGLFRenderer = new GLFrameRenderer(this, mGLSurface);
mGLSurface.setRenderer(mGLFRenderer);
B 再就是看下GLFrameRenderer怎么来写了
public class GLFrameRenderer implements Renderer {
private ISimplePlayer mParentA //请无视之
private GLSurfaceView mTargetS
private GLProgram prog = new GLProgram(0);
private int mVideoWidth = -1, mVideoHeight = -1;
private ByteB
private ByteB
private ByteB
public GLFrameRenderer(ISimplePlayer callback, GLSurfaceView surface) {
mParentAct = //请无视之
mTargetSurface =
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
Utils.LOGD(&GLFrameRenderer :: onSurfaceCreated&);
if (!prog.isProgramBuilt()) {
prog.buildProgram();
Utils.LOGD(&GLFrameRenderer :: buildProgram done&);
public void onSurfaceChanged(GL10 gl, int width, int height) {
Utils.LOGD(&GLFrameRenderer :: onSurfaceChanged&);
GLES20.glViewport(0, 0, width, height);
public void onDrawFrame(GL10 gl) {
synchronized (this) {
if (y != null) {
// reset position, have to be done
y.position(0);
u.position(0);
v.position(0);
prog.buildTextures(y, u, v, mVideoWidth, mVideoHeight);
GLES20.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);
prog.drawFrame();
* this method will be called from native code, it happens when the video is about to play or
* the video size changes.
public void update(int w, int h) {
Utils.LOGD(&INIT E&);
if (w & 0 && h & 0) {
if (w != mVideoWidth && h != mVideoHeight) {
this.mVideoWidth =
this.mVideoHeight =
int yarraySize = w *
int uvarraySize = yarraySize / 4;
synchronized (this) {
y = ByteBuffer.allocate(yarraySize);
u = ByteBuffer.allocate(uvarraySize);
v = ByteBuffer.allocate(uvarraySize);
mParentAct.onPlayStart(); //请无视之
Utils.LOGD(&INIT X&);
* this method will be called from native code, it's used for passing yuv data to me.
public void update(byte[] ydata, byte[] udata, byte[] vdata) {
synchronized (this) {
y.clear();
u.clear();
v.clear();
y.put(ydata, 0, ydata.length);
u.put(udata, 0, udata.length);
v.put(vdata, 0, vdata.length);
// request to render
mTargetSurface.requestRender();
代码很简单,Renderer主要处理这么几个事:
1.Surface create的时候,我初始化了一些需要用到的Program/Shader,因为马上就要用到它们了;
2.Surface change的时候,重置一下画面;
3.onDrawFrame()时,把数据真正地“画”上去;
4.至于两个update方法,是用来把图像的宽高/数据传过来的。
C 看GLProgram是怎么写的,它的作用是向Renderer提供计算单元,你所有对数据的处理,都在这儿了。
public boolean isProgramBuilt() {
return isProgB
public void buildProgram() {
createBuffers(_vertices, coordVertices);
if (_program &= 0) {
_program = createProgram(VERTEX_SHADER, FRAGMENT_SHADER);
Utils.LOGD(&_program = & + _program);
* get handle for &vPosition& and &a_texCoord&
_positionHandle = GLES20.glGetAttribLocation(_program, &vPosition&);
Utils.LOGD(&_positionHandle = & + _positionHandle);
checkGlError(&glGetAttribLocation vPosition&);
if (_positionHandle == -1) {
throw new RuntimeException(&Could not get attribute location for vPosition&);
_coordHandle = GLES20.glGetAttribLocation(_program, &a_texCoord&);
Utils.LOGD(&_coordHandle = & + _coordHandle);
checkGlError(&glGetAttribLocation a_texCoord&);
if (_coordHandle == -1) {
throw new RuntimeException(&Could not get attribute location for a_texCoord&);
* get uniform location for y/u/v, we pass data through these uniforms
_yhandle = GLES20.glGetUniformLocation(_program, &tex_y&);
Utils.LOGD(&_yhandle = & + _yhandle);
checkGlError(&glGetUniformLocation tex_y&);
if (_yhandle == -1) {
throw new RuntimeException(&Could not get uniform location for tex_y&);
_uhandle = GLES20.glGetUniformLocation(_program, &tex_u&);
Utils.LOGD(&_uhandle = & + _uhandle);
checkGlError(&glGetUniformLocation tex_u&);
if (_uhandle == -1) {
throw new RuntimeException(&Could not get uniform location for tex_u&);
_vhandle = GLES20.glGetUniformLocation(_program, &tex_v&);
Utils.LOGD(&_vhandle = & + _vhandle);
checkGlError(&glGetUniformLocation tex_v&);
if (_vhandle == -1) {
throw new RuntimeException(&Could not get uniform location for tex_v&);
isProgBuilt =
* build a set of textures, one for Y, one for U, and one for V.
public void buildTextures(Buffer y, Buffer u, Buffer v, int width, int height) {
boolean videoSizeChanged = (width != _video_width || height != _video_height);
if (videoSizeChanged) {
_video_width =
_video_height =
Utils.LOGD(&buildTextures videoSizeChanged: w=& + _video_width + & h=& + _video_height);
// building texture for Y data
if (_ytid & 0 || videoSizeChanged) {
if (_ytid &= 0) {
Utils.LOGD(&glDeleteTextures Y&);
GLES20.glDeleteTextures(1, new int[] { _ytid }, 0);
checkGlError(&glDeleteTextures&);
// GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
checkGlError(&glGenTextures&);
_ytid = textures[0];
Utils.LOGD(&glGenTextures Y = & + _ytid);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _ytid);
checkGlError(&glBindTexture&);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, _video_width, _video_height, 0,
GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, y);
checkGlError(&glTexImage2D&);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
// building texture for U data
if (_utid & 0 || videoSizeChanged) {
if (_utid &= 0) {
Utils.LOGD(&glDeleteTextures U&);
GLES20.glDeleteTextures(1, new int[] { _utid }, 0);
checkGlError(&glDeleteTextures&);
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
checkGlError(&glGenTextures&);
_utid = textures[0];
Utils.LOGD(&glGenTextures U = & + _utid);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _utid);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, _video_width / 2, _video_height / 2, 0,
GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, u);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
// building texture for V data
if (_vtid & 0 || videoSizeChanged) {
if (_vtid &= 0) {
Utils.LOGD(&glDeleteTextures V&);
GLES20.glDeleteTextures(1, new int[] { _vtid }, 0);
checkGlError(&glDeleteTextures&);
int[] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
checkGlError(&glGenTextures&);
_vtid = textures[0];
Utils.LOGD(&glGenTextures V = & + _vtid);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _vtid);
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_LUMINANCE, _video_width / 2, _video_height / 2, 0,
GLES20.GL_LUMINANCE, GLES20.GL_UNSIGNED_BYTE, v);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);
* render the frame
* the YUV data will be converted to RGB by shader.
public void drawFrame() {
GLES20.glUseProgram(_program);
checkGlError(&glUseProgram&);
GLES20.glVertexAttribPointer(_positionHandle, 2, GLES20.GL_FLOAT, false, 8, _vertice_buffer);
checkGlError(&glVertexAttribPointer mPositionHandle&);
GLES20.glEnableVertexAttribArray(_positionHandle);
GLES20.glVertexAttribPointer(_coordHandle, 2, GLES20.GL_FLOAT, false, 8, _coord_buffer);
checkGlError(&glVertexAttribPointer maTextureHandle&);
GLES20.glEnableVertexAttribArray(_coordHandle);
// bind textures
GLES20.glActiveTexture(_textureI);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _ytid);
GLES20.glUniform1i(_yhandle, _tIindex);
GLES20.glActiveTexture(_textureII);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _utid);
GLES20.glUniform1i(_uhandle, _tIIindex);
GLES20.glActiveTexture(_textureIII);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, _vtid);
GLES20.glUniform1i(_vhandle, _tIIIindex);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glFinish();
GLES20.glDisableVertexAttribArray(_positionHandle);
GLES20.glDisableVertexAttribArray(_coordHandle);
* create program and load shaders, fragment shader is very important.
public int createProgram(String vertexSource, String fragmentSource) {
// create shaders
int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
// just check
Utils.LOGD(&vertexShader = & + vertexShader);
Utils.LOGD(&pixelShader = & + pixelShader);
int program = GLES20.glCreateProgram();
if (program != 0) {
GLES20.glAttachShader(program, vertexShader);
checkGlError(&glAttachShader&);
GLES20.glAttachShader(program, pixelShader);
checkGlError(&glAttachShader&);
GLES20.glLinkProgram(program);
int[] linkStatus = new int[1];
GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
if (linkStatus[0] != GLES20.GL_TRUE) {
Utils.LOGE(&Could not link program: &, null);
Utils.LOGE(GLES20.glGetProgramInfoLog(program), null);
GLES20.glDeleteProgram(program);
program = 0;
* create shader with given source.
private int loadShader(int shaderType, String source) {
int shader = GLES20.glCreateShader(shaderType);
if (shader != 0) {
GLES20.glShaderSource(shader, source);
GLES20.glCompileShader(shader);
int[] compiled = new int[1];
GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
if (compiled[0] == 0) {
Utils.LOGE(&Could not compile shader & + shaderType + &:&, null);
Utils.LOGE(GLES20.glGetShaderInfoLog(shader), null);
GLES20.glDeleteShader(shader);
shader = 0;
* these two buffers are used for holding vertices, screen vertices and texture vertices.
private void createBuffers(float[] vert, float[] coord) {
_vertice_buffer = ByteBuffer.allocateDirect(vert.length * 4);
_vertice_buffer.order(ByteOrder.nativeOrder());
_vertice_buffer.asFloatBuffer().put(vert);
_vertice_buffer.position(0);
if (_coord_buffer == null) {
_coord_buffer = ByteBuffer.allocateDirect(coord.length * 4);
_coord_buffer.order(ByteOrder.nativeOrder());
_coord_buffer.asFloatBuffer().put(coord);
_coord_buffer.position(0);
private void checkGlError(String op) {
while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
Utils.LOGE(&***** & + op + &: glError & + error, null);
throw new RuntimeException(op + &: glError & + error);
private static float[] squareVertices = { -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, 1.0f, 1.0f, }; // fullscreen
private static float[] coordVertices = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, };// whole-texture
private static final String VERTEX_SHADER = &attribute vec4 vP\n& + &attribute vec2 a_texC\n&
+ &varying vec2\n& + &void main() {\n& + &gl_Position = vP\n& + &tc = a_texC\n& + &}\n&;
private static final String FRAGMENT_SHADER = &pre\n& + &uniform sampler2D tex_y;\n&
+ &uniform sampler2D tex_u;\n& + &uniform sampler2D tex_v;\n& + &varying vec2\n& + &void main() {\n&
+ &vec4 c = vec4((texture2D(tex_y, tc).r - 16./255.) * 1.164);\n&
+ &vec4 U = vec4(texture2D(tex_u, tc).r - 128./255.);\n&
+ &vec4 V = vec4(texture2D(tex_v, tc).r - 128./255.);\n& + &c += V * vec4(1.596, -0.813, 0, 0);\n&
+ &c += U * vec4(0, -0.392, 2.017, 0);\n& + &c.a = 1.0;\n& + &gl_FragColor =\n& + &}\n&;
这里面代码比较复杂,我在这里稍作解释:
1.首先,buildProgram()目的要生成一个program,作用是用来将YUV-&RGB,其中用到了2个shader(shader就相当于一个小运算器,它运行一段代码),第1个shader运行VERTEX_SHADER里的代码,目的是将坐标作为参数传入第2个shader;第2个shader来做YUV-&RGB的运算。
2.buildTextures()是要生成3个贴图,分别为了显示R/G/B数据,三个贴图重合在一起,显示出来的就是彩色的图片。
3.drawFrame()是使用program来做运算,并真正去做画这个动作了。
至此,就可以将YUV图片也好,视频也可,给显示在Android上了,而且速度不慢哦!希望能帮到大家。
相关代码下载链接:
http://download.csdn.net/detail/ueryueryuery/7144851
木有分的同学,可以发邮件至,写明需要哪份代码,LOL
========================================================
以上代码只是关键类的代码,也搭者楼主懒,一直没有写一个完整的demo。
不过,只要大家多从网上查查,再结合楼主的类,一定可以自己搞出来的!
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:69689次
排名:千里之外
原创:17篇
评论:164条
(1)(1)(3)(4)(2)(1)(1)(5)(5)《OpenGLES 2.0 Programming Guide》学习笔记(持续更新) - 推酷
《OpenGLES 2.0 Programming Guide》学习笔记(持续更新)
创立,目前有
继承而来,
继承而来。
的图形流水线,灰色的方框是可编程阶段。
实现了一种作用于顶点的通用可编程方法。
的输入由以下几种组成:
由顶点数组提供的
使用的常量数据
一种特殊的
使用的纹理。
是可选的。
程序,源代码或者可执行的,描述了对于顶点进行的操作。
的输出叫做
的值对于每个生成的
进行计算,并将结果作为输入传递给
。从赋予图元每个顶点的
值的机制叫做插值
的输入输出图:
可用来进行传统的基于顶点的操作,例如使用矩阵变换位置、进行光照计算产生一个
的颜色、生成或变换纹理坐标。然而,因为
是一个程序,
可以用来进行任意的自定义顶点变换。
一个简单的
是一个内置的
不用声明,
必须向它写入。
唯一的入口点。
图元装配阶段
之后的流水线阶段就是图元装配,所谓图元是指可以用
绘制命令绘制的基本几何体。图元由顶点组成,顶点有各种属性,如位置和颜色。
使用这些属性进行计算。在图元集成阶段,经过
的顶点被集成进一个个独立的几何图元中,例如三角形,线或点精灵。对于每个图元,必须对其进行
裁剪。如果图元部分在
,如果图元完全在
外则被丢弃。
之后,顶点的位置被转换到屏幕坐标系。另外,背面剔除也会在这阶段进行。这之后,图元就准备被传送到下一个阶段
光栅化阶段
光栅化将图元转化成二维片段
的集合,这些片段将被
表示了可以被绘制到屏幕上的像素。
注:图元的属性是之前
,在光栅化阶段,基于图元的
值被插值计算为基于片段的
实现了一种作用于片段的通用可编程方法。
对光栅化阶段产生的每个片段进行操作。
经过光栅化插值后对每个片段产生的值。
使用的常量数据
:一种特殊类型的
使用的纹理
程序,代码或可执行的,描述了对于片段的操作。
可以丢弃片段或者为片段生成一个颜色,输出保存到
光栅化阶段生成的
和窗口坐标
将会成为流水线
操作阶段的输入(
之后的阶段)。
一个简单的
必须写这个
是唯一的输出
之后就是逐片段操作阶段。光栅化产生的一个片段,具有窗口坐标
,只能修改
阶段的操作过程:
是用来决定
中某个位置的像素是否属于
,比如如果
的显示窗口被其他窗口遮住了,则一些像素就通不过这个测试,也就不会被
显示。(似乎程序不需要控制这个)
的片段是否在
矩形内,如果不在,片段被丢弃。
值,决定片段是否被丢弃。
:将新产生的片段的颜色和
中相应位置像素的颜色进行混合。
阶段之后,
处的片段要么被拒绝要么会产生一个
值是否真的写入
还取决于相应的
也提供了从
回读像素的接口,但只有
可以回读,
值是读不到的。
中支持,需要在
被去掉了,因为很少使用。(
中是存在的)
不向后兼容
中的固定功能流水线。
中的固定功能顶点处理单元,即:顶点
,纹理坐标生成和变换,顶点颜色计算。
的固定功能
单元,即为每个
是完全向后兼容的,同时支持可编程流水线和固定流水线。)
命令需要一个
是图元绘制上去的
指定了渲染所需的
的类型,例如
,以及每种
不提供如何创建
之间的接口。然而厂商在实现
时并不一定提供
,不同平台可能有各自的接口。
必须且仅能
可以在任意时刻进行,哪怕
,甚至没有
不会立即删除这个
会被标记为待删除,一旦这个
的内存将被释放。
会检查,确保
使用的所有
写入,并且被声明成同样的类型
会检查,确保
具有匹配的类型
会确保最终的
适合实现的限制(即,
的数量,使用的指令)
阶段会产生最终的硬件指令(
有些问题如纹理没有被绑定到
时是不能查到的,可使用
是否可以在当前状态下执行。这个操作很慢,一般只在
版本中使用。
应用程序通过通过
的只读变量
中是共享的,即一个
中声明,必须具有相同的类型,并且在这两个
的值是一样的。在
。应用程序使用这个
作为标识来载入
需要手动查询得到
中实际使用的
,如果仅仅是声明不算。
值,首先使用
的名字,以及数据类型
数组元素数
如果不是数组
。这样就可以使用一系列的
的时候,不用
作为参数,因为这是针对当前
的。但是一旦为一个
设置了值后,这个值将会保存在这个
变量可以在声明时初始化也可以以后初始化。初始化通过使用构造器完成,构造器也被用作类型转换。
变量构造器
的类型转换是很严格的,变量只能被赋值给相同类型的变量或者和相同类型的变量一起计算。为了进行类型转换,语言中有很多构造器。
向量的构造
单标量参数
向量所有分量值设置为该标量
多标量或向量参数构造– 向量分量从左到右赋值,参数必须够用
矩阵的构造
如果只提供一个标量参数,这个值被设置在矩阵对角线上,例如
会构造一个
矩阵可用多个向量构造;可用多个标量构造;或者向量和标量混搭构造。
访问向量和矩阵的成员
向量可用点访问
或数组下标访问。可以用
这几种分量名字,但不可混用。
向量可通过点访问重新排序,如:
下标访问,从
;下标如果不是常量,
可能不支持。
矩阵被看出是由很多向量组成。例如
组成。矩阵的列用数组下标选择。
然后每个列向量使用向量访问规则。例如:
可定任意基本类型的常量。常量变量在
中值不改变。常量必须在声明时初始化。
关于数组的重要事项:
实现不允许使用无法在编译时确定值的变量去索引数组。
)不能在创建时初始化数组
没有这样的语法。因此,数组不能是常量。数组元素需要逐个初始化。
操作必须使用于具有相同基本类型的变量之间
基本类型必须是
,乘法可在
(只能作用于标量,要比较向量使用内置函数)
(逻辑异或)
类似,最大的区别在于参数的传入方式。
提供了特定的修饰符来定义参数是否可以被函数修改:
默认,如果不指定)
,不会被函数修改
如果被修改,函数返回后改变值。
变量的值不传入函数,函数返回时变量修改。
例子,计算
光照的函数:
另外,函数不可以递归,因为一些实现会以
的方式实现函数调用。
使用例子,计算高光:
类似,但有很多限制。
)判断表达式必须是
变量或者比较表达式),因为
不支持隐式转换。
)使用循环有各种限制,归结为:
必须在编译时知道迭代数。
必须只有一个循环迭代变量,并且只能使用简单的表达式增加或减少(
循环的结束条件判断必须是循环索引和一个常量表达式之间的比较;
不能在循环中改变迭代变量的值;
不需要实现真正支持
它这样限制
是为了让编译器可以将
变量保存应用程序通过
的只读值。
使用的各种数据,如变换矩阵,光的参数或者颜色。基本上,
需要使用的任意参数如果对于所有的顶点和片段都是常量(但在编译时不知道)应该传入给
变量在全局范围内定义:
存储于硬件上的“
可使用的数量有限制。
中使用,用于指定
的输入。通常保存位置,法线,纹理坐标,颜色等数据。
数量的限制:至少是
的输入(在光栅化时进行了图元内线性插值)。在
中的声明必须一致。
在硬件上就是
,数量至少为
预处理器和指令
宏定义和测试指令:
宏不能用参数定义;
测试某个宏是否定义。
预定义的宏:
指令会在编译
时引发一个编译错误并将
指定用于编译器实现相关的指令。
指令用于表示
语言的版本,必须写在最上面,目前版本是
用于厂商对语言的扩展。
存储布局为
自动进行。
用于指定任意基于
类型的变量。
如果变量没有指定精度,则使用默认精度。默认精度在
代码头部指定:
用于所有基于浮点数值的变量
用于所有基于整型值的变量
中,如果没有指定默认精度,则
的默认精度都是
类型的默认精度没有默认值,必须显示的声明。并且在
中,不一定支持
可查询得知是否支持(
定义,或者查询
关键字可以作用于
输出的任意
在编译时,编译器可能进行优化,导致指令被重排。这意味着两个
间相同的计算,不一定产生精确相等的结果。这对于
渲染来说是个问题,一个物体被渲染多次,如果计算出来的位置有差别,就会有瑕疵。比如产生
时指定如果使用了相同的计算,输出的结果必须精确一致。
关键字可以使用在
声明上或者已经声明的
内置的已经声明的
声明时使用
指令器然所有的变量
注意,为了实现
编译器限制了优化,所有仅当需要时才使用
数据和他们支持的数据类型?
中相应的顶点
名字绑定?
顶点数据或称为顶点属性,是给每个顶点指定的数据,可以每个顶点逐一指定也可所有顶点使用一个常量值。
中,顶点属性有预定义的名字,例如
。因为固定流水线只需要这些顶点属性,所以预定义这些属性是合理的。在可编程流水线中,开发者需要在
中使用他们自己的顶点属性名字,因此对于
,用户自定义顶点属性名是必须的,既然如此,预定义名字也就不需要了。
如何指定顶点属性数据?
逐个顶点指定属性数据使用
;图元的所有顶点使用相同数据则使用常量值。
查询支持的最大顶点属性数,用glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,&maxVertexAttribs);
这个值至少为8。
图元中所有顶点如果使用相同属性值就只用常量顶点属性
常量顶点属性只能使用GLfloat,通过glVertexAttrib1/2/3/4f[v]指定。例如:
void glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z);
这个函数将(x,y,z,1.0)设定到索引为index的顶点属性上。
vertex arrays为每个顶点指定属性数据,他们是存储在应用程序地址空间的buffer(即client space)。
vertex array提供了一种高效而灵活的方式来指定顶点属性数据。要指定vertex array,需要使用
glVertexAttribPointer函数:
void glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *ptr)
index: 指定通用顶点属性的索引,取值为0到支持的最大顶点属性数-1
顶点数组中,
index所引用的顶点属性的组件数。有效值为1-4
type: 数据格式。有效值为:GL_BYTE, GL_UNSIGNED_BYTE, GL_SHORT, GL_UNSIGNED_SHORT, GL_FLOAT, GL_FIXED, GL_HALF_FLOAT_OES
normalized: 用于指出是否非浮点数据格式在被转换为浮点数时是否需要归一化。
stride: size参数所指定的顶点属性组件们是为逐顶点顺序存储在顶点数组中的。stride指出了顶点i和顶点i+1数据之间的差值。如果stride是0,所有顶点的属性数据是序列存储的。如果stride&0,stride作为一个pitch值来获取下一个顶点的数据。
顶点数组存储方式:
1)array of structures: 所有顶点属性存储在同一个单一的buffer中
2)structure of arrays: 每种顶点属性存储在一个独立的buffer中
在vertex shader中定义attribute
attribute vec4 a_
attribute vec2 a_
attribute vec3 a_
attribute修饰符只能出现在vertex shader中,在fragment shader中会导致编译错误;attribute只能是float, vec2, vec3, vec4, mat2, mat3, mat4类型的。attribute变量不能是数组或者结构。
ES2.0实现支持GL_MAX_VERTEX_ATTRIBS个vec4类型的vertex attributes。float, vec2, vec3被计算做一个vec4。mat2,mat3,mat4分别计算为2,3,4个vec4。不像uniform和varying变量可以被自动pack,attribute不会被pack。
attribute变量在shader中是只读的。
在vs中定义的attribute如果没有使用是不会被认为激活的,也不会计算为使用的容量。
如果attribute的总量超过了GL_MAX_VERTEX_ATTRIBS,vertex shader会link失败。
一旦program成功被link,我们可以查出这个program的vs使用的active的vertex attribute数量:
glGetProgramiv(program, GL_ACTIVE_ATTRIBUTES, &numActiveAttribs);
已发表评论数()
&&登&&&陆&&
已收藏到推刊!
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见}

我要回帖

更多关于 jquery获取自身html 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信