OpenGL着色器语言
来源:互联网 发布:数据专员这工作好吗 编辑:程序博客网 时间:2024/05/21 17:08
初识OpenGL着色器语言
未完待续:
1、着色器架构
OpenGL着色器语言(GLSL)由OpenGL实现链接和编译,完全在图形硬件中运行。
至少需要两个着色器
- 顶点着色器
- 片段着色器。
- 还有一种可选的着色器称为几何着色器。
我们可以在3中方式中选择一种向顶点着色器传递数据:
- 参数,是对每个顶点而言的。
- 统一值,是针对整个顶点数据批次的常量。
- 加载和使用纹理数据。
可以为片段着色器设置统一值和纹理数据。
注意:将顶点属性发送到片段着色器毫无意义,因为片段着色器只是用来在土元进行光栅化后对片段进行填充(最基本的是像素)。
着色器程序的从入口点main函数开始。
2、变量和数据类型
数据类型:
- 整数(有符号和无符号)
- 浮点数(单精度)
布尔值
没有指针,且没意任何类型的字符串和字符。但函数可以还回这些类型的一种,也可以声明为void。
向量类型:
我们可以使用一个“构造函数初始化一个向量。
例如:
vec4 vVertexPos = vec4(39.0f, 10.0f, 0.0f, 1.0f);
有关向量的操作:
vVertexPos = vOldPos + vOffset; //两个向量相加vVertexPos = vNewPos; //赋值vVertexPos = vec4(1.0f, 1.0f, 0.1f, 0.0f); vVertexPos *= 5.0f; //进行缩放
可以对独立元素进行寻址:
1.典型情况下:
vVertexPos.x = 3.0f;vVertexPos.xy = vec2(3.0f, 5.0f);vVertexPos.xyz = vNewPos.xyz;
2.进行颜色操作时使用rgba:
vOutputColor.r = 1.0f;
3.进行纹理操作时用stpq。
4.向量类型还支持调换操作:
如:
vNewColor.bgra = vOtherVertex.x + 5.0f;
向量类型不只是着色器的本地数据类型,也是硬件的数据类型,速度很快。
矩阵类型:
所以的矩阵只支持浮点数。
一个矩阵就是一个向量组成的数组—-列向量
矩阵的相关操作:
mModelView[3] = vec4(0.0f, 0.0f, 0.0f, 1.0f); /*设置矩阵的最后一列*/vec4 vTranslation = mModelView[3]; /*恢复一个矩阵的最后一列*/vec4 vTranslation = mModelView[3].xyz; /**/vec4 vVertex;mat4 mvpMatrix;vOutPos = mvpMatrix * vVertex; //矩阵乘以向量mat4 vTransform = mat4(1.0f); //构造一个单位矩阵
3、存储限定符
——限定符用于将变量标记为输入变量(in或uniform)、输出变量(out)或常量。
- 输入变量:接受来自OpenGL客户端(通过C/C++提交的属性)或者以前的着色器阶段(例如从顶点着色器传递到片段着色器)。
- 输出变量:指在任何着色器阶段进行写入的变量,我们希望在后续的着色器阶段能看到这些变量。如,从顶点着色器传递到片段着色器。
补充:
1. inout只能在一个函数中声明一个参数时使用。这是将一个值传递 到一个函数并且允许这个函数修改并还回同一变量值得唯一方法。
2. 在但采样缓存区中,插值操作总是从像素中心开始的,限定符controid只对一个多重采样缓存区起作用。
3. 默认情况下,参数将在两个着色器阶段之间以一种透视正确的方法进行插补。noperspective关键字来指定一个非透视插值,flat关键词不进行插值,smooth是以一种透视正确的方法进行插补。
4、真正的着色器
GLShanderManager类有个单位存储着色器。—–这种着色器不会对集合图像进行转换,而是使用单一的颜色来绘制图元。
ShadedIdentity顶点程序:
#version 330 //指定着色器要求的OpneGL着色语言的最低版本为3.3//属性声明in vec4 vVertex; //顶点位置属性in vec4 vColor; //顶点颜色属性out vec4 vVaryingColor; /*传递到片段着色器的颜色值,这个变量将成为要传递到片段着色器的顶点的颜色值,逐个着变量必须为片段着色器声明一个in变量*/void main(void){ vVaryingColor = vColor; // 简单复制颜色值 gl_Postion = vVertex; //简单传递顶点位置}
ShadedIdentity着色器片段程序:
#version 330out vec4 vFragColor; //将要进行光栅化的片段颜色in vec4 vFrayingColor; //从顶点阶段得到的颜色void main(void){ vFragColor = vVaryingColor; //对片段进行颜色插值}
- 属性声明:是由C/C++客户端OpenGL代码逐个顶点进行指定的,每个顶点程序中最多可以有16个属性。另外,标记为in的变量是只读的。
- 顶点动作:主函数main中的内容,gl_Position是一个预定义的内建4个分量向量,它包含顶点着色器要求的一个输出。输入gl_Position的值是集合图形阶段用来装配图元的。
- 片段三角形:在渲染一个图元时,一旦3个顶点有顶点程序进行处理,那么他们将组成一个三角形,这个三角形将由硬件进行光栅化。如果片段程序只有一个输出,那么它在内部将被分配为“输出0”。这个片段着色器的一个输出,并将传递到有glDrawBuffers设置的缓存区目标。
5、编译、绑定和链接
顶点着色器的后缀名.vp。
片段着色器的后缀名.fp。
gltLoadShaderPairWithAttributes函数
///////////////////////////////////////////////////加载一对着色器,进行编译并链接到一起//为每个着色器指定完整的源文本//在着色器名之后,指定参数数量,然后指定索引和每个参数的参数名GLuint gltLoadShaderPairWithAttributes(const char *szVertexProg, const char *szFragmentProg, ......){ //临时着色器对象 GLuint hVertexShader; GLuint hFragmentShader; GLuint hReturn = 0; GLint testVal; //创建着色器对象 hVertexShader = glCreateShader(GL_VERTEX_SHADER); hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER); //加载他们,如果失败则进行清除并还回null //顶点程序 if(gltLoadShaderFile(szVertexProg, hVertexShader) == false) { glDeleteShader(hVertexShader); glDeleteShader(hFragmentShader); cout << "The shader at "<< szVertexProg << "could not be found.\n"; return (GLuint)NULL; } //片段程序 if(gltLoadShaderFile(szFragmentProg, hVFragmentShader) == false) { glDeleteShader(hVertexShader); glDeleteShader(hFragmentShader); cout << "The shader at "<< szFragmentProg << "could not be found.\n"; return (GLuint)NULL; } //对两者进行编译 glCompileShader(hVertexShader); glCompileShader(hFragmentShader); //在顶点着色器检查错误 glGetShaderiv(hVertexShader, GL_COMPILE_SHADER, &testVal); if(testVal == GL_FLASE) { char infoLog[1024]; glGetShaderInfoLog(hVertexShader, 1024, NULL, infoLog); cout<<"The shader at"<<szVertexProg <<" failed to compile with the following error:\n"<< infoLog << "\n"; glDeleteShader(hVertexShader); glDeleteShader(hFragmentShader); return (GLuint)NULL; } //在片段着色器检查错误 glGetShaderiv(hFragmentShader, GL_COMPILE_SHADER, &testVal); if(testVal == GL_FLASE) { char infoLog[1024]; glGetShaderInfoLog(hFragmentShader, 1024, NULL, infoLog); cout<<"The shader at"<<szFragmentProg <<" failed to compile with the following error:\n"<< infoLog << "\n"; glDeleteShader(hVertexShader); glDeleteShader(hFragmentShader); return (GLuint)NULL; } //创建最终的程序对象,并链接着色器 hReturn = glCreateProgram(); glAttrachShader(hReturn,hVertexShader); glAttrachShader(hReturn,hFragmentShader); //现在需要将参数名绑定到他们指定的参数位置列表上 va_list attributeList; va_start(attributeList, szFragmentShader); //重复迭代这个参数列表; char *szNextArg; int iArgCount = va_arg(attributeList, int); //参数数量 for(int i = 0; i < iArgCount; i++) { int index = va_arg(attributeList, int); szNextArg = va_arg(attributeList, char*); glBindAttribLocation(hReturn, index, szNextArg); } va_end(attributeList); //尝试连接 glLinkProgram(hReturn); //这些不在需要了 glDeleteShader(hVertexShader); glDeleteShader(hFragmentShader); //确认连接也有效 glGetProgramiv(hReturn, GL_LINK_STATUS, &testVal); if(testVal == GL_FLASE) { char infoLog[1024]; glGetProgramInfoLog(hReturn, 1024, NULL, infoLog); cout<<"The program "<<hReturn <<" failed to link with the following error:\n"<< infoLog<< "\n"; glDeleteProgram(hReturn); return (GLuint)NULL; } return hReturn;}
加载一个着色器所以必须元素:
- 指定属性:例如,
hShader = gltLoadShaderPairWithAttributes("vertexProg.vp", fragmentProg.fp, 2, 0, "vVertexPos", 1, "vNormal");
用来绑定一个带有顶点位置和表面法线属性的着色器。 - GLTools类GLBatch和GLTriangleBatch使用一系列一直的属性位置,
typedef enum GLT_SHADER_ATTRIBUTE{GLUT_ATTRIBUTE_VERTEX = 0,
GLUT_ATTRIBUTE_COLOR, GLUT_ATTRIBUTE_NORNAL,
GLUT_ATTRIBUTE_TEXTURE0, GLUT_ATTRIBUTE_TEXTURE1,
GLUT_ATTRIBUTE_TEXTURE2, GLUT_ATTRIBUTE_TEXTURE3,
GLUT_ATTRIBUTE_LAST };
使用这些属性位置标识符,我们就可以开始和GLShaderManager类中支持的存储着色器一起使用自己的着色器了。 - 设置源代码:
首要任务是创建两个着色器对象,分别对应顶点着色器和片段着色器。
hVertexShader = glCreateShader(GL_VERTEX_SHADER);hFragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
然后,可以使用者两个着色器ID来加载着色器源代码。
GLchar *fsStringPtr[1];
fsStringPtr[0] = (GLchar *)szShaderSrc;
glShaderSource(shader, 1, (const GLchar **)fsStringPtr, NULL);
- 编译着色器
- 进行连接和绑定
- 连接着色器
6、使用着色器
glUseProgram(myShaderProgram);
将着色器设置成活动的,这样在顶点和片段着色器会处理所以提交的几何图形。在提交顶点属性之前,要对Uniform值和纹理进行设置。
着色器统一值
1、寻址统一值
在着色器编译和链接后,我们必须在着色器中寻找统一值位置。
GLint glGetUniformLocation(GLuint shaderID, const GLchar * varName);
代表在shaderID指定的着色器中由valName命名的变量的位置。
void glUniform1f(GLint location, GLfloat v0);void glUniform2f(GLint location, GLfloat v0, GLfloat v1); . . .void glUniform4i(GLint Location, GLint v0, GLint v1, GLint v2, GLint v3);
例如:
uniform float fTime;
uniform int iIndex;
uniform vec4 vColorValue;
uniform bool bSomeFlag;
//为了在着色器中寻找并这些值,代码如下:
GLint locTime, locIndex, locColor, locFlag;
locTime = glGetUniformLocation(myShader, "fTime");
locIndex = glGetUniformLocation(myShader, "iIndex");
locColor = glGetUniformLocation(myShader, "vColorValue");
locFlag = glGetUniformLocation(myShader, "bSomeFlag");
......
......
glUseProgram(myShader);
glUniform1f( locTime, 45.2f);
glUniform1i(locIndex, 42);
glUniform4f(locColor, 1.0f, 0.0f, 0.0f , 1.0f);
- OpenGL 着色器语言
- OpenGL着色器语言
- OpenGL ES着色器语言之着色
- OpenGL ES着色器语言之着色
- OpenGL 着色器语言概述
- opengl es 着色器语言
- OpenGL 着色器语言GLSL的数据类型
- OpenGL 着色器语言3.1-3.3
- OpenGL着色器语言3.4-3.8
- OpenGL着色器语言 4-4.1.3
- WebGL中的OpenGL着色器语言
- OpenGL ES着色器语言 常量、变量
- OpenGL ES着色语言
- OpenGL着色语言GLSL
- OpenGL着色语言GLSL
- opengl es 2.0 读书笔记2-OpenGL ES 着色器语言
- OpenGL ES2.0----着色语言
- OpenGL ES着色语言-UBO
- 更新高德地图语音模块
- LeetCode - 55. Jump Game
- android studio优化设置
- Java之:Threadlocal
- M - 人见人爱A+B Time Limit:1000MS Memory Limit:32768KB 64bit IO Format:%I64d & %I64u
- OpenGL着色器语言
- 外网全量机器抓包/日志
- ModelAttribute的使用 关于请求参数和URL模板
- python学习——高阶函数
- 基于Retrofit+Okio+RxBus实现文件下载(带下载进度)
- oracle导入dmp文件
- CodeForces 682B
- XML新手入门 创建构造良好的XML(1)
- Android网络知识总结