opengles2——3.着色器和编程
来源:互联网 发布:亚马逊大数据选品 编辑:程序博客网 时间:2024/06/07 01:23
【着色器和项目】
使用着色器渲染有两个基本的对象类型你需要去创建:着色器对象和项目对象。着色器对象是包含单个着色器的物体。源码输入着色器对象,
着色器对象被编辑为目标格式(.obj文件)。完成后着色器对象能链接到项目对象上,一个项目可有多个着色器。opengles一个项目中有一个顶点
着色器和一个片段着色器(不能多不能少),然后链接成可执行文件,最后能用来渲染。
为产生链接着色器目标,首先要创建顶点着色器和片段着色器,编译源码创建项目,然后编译链接。
创建着色器:GLuint glCreateShader(GLenum type) // type是GL_VERTEX_SHADER或GL_FRAGMENT_SHADER
删除着色器:void glDeleteShader(GLuint shader)
若着色器正连接着一个项目对象,glDeleteShader不立刻删除着色器,而是设置删除标记,一旦着色器不再链接项目对象,才删除其内存。
提供着色器源码:void glShaderSource(GLuint shader, GLsizei count, const char** string, const GLint *length)
编译着色器:void glCompileShader(GLuint shader)
查询错误:void glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
回忆下加载着色器的代码:
GLuint LoadShader( GLenum type, const char *shaderSrc ){GLuintshader;GLintcompliled;// 创建着色器对象shader = glCreateShader(type);if (!shader)return 0;// 加载着色器源glShaderSource(shader, 1, &shaderSrc, NULL);// 编译着色器glCompileShader(shader);// 测试编译状态glGetShaderiv(shader, GL_COMPILE_STATUS, &compliled);if (!compliled){GLintinfoLen = 0;glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);if (infoLen > 1){char *infoLog = new char[infoLen];glGetShaderInfoLog(shader, infoLen, NULL, infoLog);esLogMessage("Error compliling shader:\n%s\n", infoLog);delete infoLog;}glDeleteShader(shader);return 0;}return shader;}
【创建和链接项目】
项目 是 你创建的着色器要链接到的对象及链接后可执行的程序。项目调用着色器很简单。
创建项目:GLuint glCreateProgram(void)
删除项目:void glDeleteProgram(GLuint program)
链接顶点着色器和片段着色器:void glAttachShader(GLuint program, GLuint shader)
注意着色器能在任何时候被连接,不需要编译或源码。但要求一个项目只能有一个顶点着色器和一个片段着色器。
也可使用glDetachShader分离一个着色器:void glDetachShader(GLuint program, GLuint shader)
着色器连接后需要链接着色器,使用glLinkProgram: void glLinkProgram(GLuint program)
链接产生最后的可执行程序。链接器将保证每个片段着色器的变量都是顶点着色器产生的(类型相同);链接器也保证所有的
片段着色器uniforms常量和顶点着色器是匹配的;...
链接后使用glGetProgramiv检查链接是否成功:void glGetProgramiv(GLuint program, GLenum pname, GLint *params)
链接成功后准备渲染。要查询项目是否有效,有一些原因会导致项目不能执行,例如程序没有对采样器绑定一个有效的贴图。
检查项目当前的执行状态:void glValidateProgram(GLuint program)
注意:若glValidateProgram只为了调试,将是缓慢的,不能在渲染前随时使用。
设置项目为实际的渲染目标:void glUseProgram(GLuint program)
回忆下项目有关的源码:
// 创建程序对象programObject = glCreateProgram();if (!programObject)return 0;glAttachShader(programObject, vertexShader);glAttachShader(programObject, fragmentShader);// 设置顶点着色器vPosition属性,绑定attribute 0glBindAttribLocation(programObject, 0, "vPosition");// 链接项目 检查错误glLinkProgram(programObject);glGetProgramiv(programObject, GL_LINK_STATUS, &linked);if (!linked){GLintinfoLen = 0;glGetProgramiv(programObject, GL_INFO_LOG_LENGTH, &infoLen);if (infoLen > 1){char *infoLog = new char[infoLen];glGetProgramInfoLog(programObject, infoLen, NULL, infoLog);esLogMessage("Error linking program:\n%s\n", infoLog);delete infoLog;}glDeleteProgram(programObject);return FALSE;}
链接项目对象时,有些查询要做。首先是找到项目使用的uniforms,输入着色器的只读变量,这些常量集也被项目对象共享。
项目对象里有一系列的常量集合,若常量被顶点着色器和片段着色器共同使用,他们的值在两个着色器里应该是相同的。链接
阶段,链接器将分配常量在项目里的实际地址,那个地址是被应用程序使用和加载的标志。
【获取和使用uniforms】
在项目里查询uniforms,可使用GL_ACTIVE_UNIFORMS参数调用glGetProgramiv,这将告诉你项目里实际的常量数目,
若常量处于active,他正在被项目使用。另外你可声明一些常量但不使用,链接器将会优化掉这些常量,不将他存储到实际使用的
常量列表中。可使用GL_ACTIVE_UNIFORM_MAX_LENGTH参数调用glGetProgramiv,找出在项目里最大的常量列表名字。
在得知实际使用的常量数目和描述的数目,可使用glGetActiveUniform查找常量的细节:
void glGetActiveUniform(GLuint program, GLuint index, GLsizei bufSize, GLsizei *length, GLint *size, GLenum *type, char *name)
index是被查询的常量索引,bufSize存储名字特征的矩阵数目..若查询出的是矩阵,size是被项目使用的最大的矩阵元素的数目(+1),
若uniform被查询出不是矩阵,这个值是1.
type是要写的uniform类型:GL_FLOAT,GL_FLOAT_VEC2,GL_FLOAT_MAT4,GL_SAMPLER_2D,GL_SAMPLER_CUBE
使用glGetActiveUniform就能知道所有的uniform的属性,能通过其类型确认它的名字。有了常量的名字后可使用glGetUniformLocation
找到他的地址,这个地址是整形,能被后面的函数使用,如glUniformlf。
GLint glGetUniformLocation(GLuint program, const char *name)
返回常量地址,若常量值在项目中未使用将返回-1.有了常量地址及类型和矩阵尺寸,可用数值装载常量,使用不同函数装载不同常量。
void glUniform1f(GLint location, GLfloat x)
void glUniforml1v(GLint location, GLsizei count, const GLfloat *v)
...
void glUniform2i(GL...)
...
void glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *value)
...
装载常量函数大部分是自动完成的,使用哪个函数装载常量取决于glGetActiveUniform函数返回的类型。注意glUniform*调用不使用项目
对象做参数。是因为他调用总是在当前的项目中绑定glUseProgram执行。常量值在项目对象中总是保持一致。即一旦你在项目里设置一个
常量值,这个值将保持不变,甚至你激活另一项目。
// 查询激活的常量GLint maxUniformLen;GLint numUniforms;char *uniformName;GLint index;glGetProgramiv(progObj, GL_ACTIVE_UNIFORMS, &numUniforms);glGetProgramiv(progObj, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);uniformName = new char[maxUniformLen];for (index = 0; index < numUniforms; ++index){GLint size;GLenum type;GLint location;// 获取信息glGetActiveUniform(progObj, index, maxUniformLen, NULL, &size, &type, uniformName);// 获取地址location = glGetUniformLocation(progObj, uniformName);switch (type){case GL_FLOAT://..break;// ..}}【获取和设置属性】
除了查询常量信息,还需要设置顶点属性。能用GL_ACTIVE_ATTRIBUTES查询到一个属性列表,能用glGetActiveAttrib查询一个属性的内容。
那是一个设置顶点矩阵,装载顶点属性值的集合。
设置顶点属性还需要一些基元和顶点着色器的知识,6章介绍。
【着色器编程和着色器二进制码】
。。。P47
- opengles2——3.着色器和编程
- Android OpenGLES2.0(七)——着色器语言GLSL
- OpenGLES2.0着色器语言教程
- OpenGLES2.0着色器语言glsl
- OpenGLES2.0着色器语言glsl
- OpenGLES着色器和编程
- OpenGLES2.0基础及着色器语言(2)
- Android OpenGLES2.0(四)——正方形和圆形
- Android OpenGLES2.0(一)——了解OpenGLES2.0
- Android OpenGLES2.0(一)——了解OpenGLES2.0
- 着色器和效果——3.2 像素着色器输入和输出
- Shader着色器基础——OpenGL编程笔记2
- 着色器和效果——1.1编写HLSL着色器
- 着色器和效果——1.2 编译HLSL着色器
- 着色器和效果——2.0 介绍顶点着色器
- 着色器和效果——2.3 使用顶点着色器的步骤
- 着色器和效果——3.0 介绍像素着色器
- 着色器和效果——3.3 使用像素着色器的步骤
- 关于结构体成员变量初始化的一些资料
- HDU 1242 Rescue(BFS+优先队列)
- 如果我最终一败涂地
- 第三周作业
- oracle 调整输出的列宽、行宽
- opengles2——3.着色器和编程
- 32 st工具 tools
- 枚举
- (No manual entry for pthread_cond_init)等问题解决方案
- 【LeetCode】Reorder List
- ubuntu 下安装activemq
- 深入分析MFC文档视图结构(项目实践)
- oracle特性之Block Change Tracking
- iPhone/Mac Objective-C内存管理教程和原理剖析