OpenGL之Shader编程入门
1.shader 编程基础
1.1 Vertex shader与Fragment shader
Vertex shader即顶点着色器,用来改变顶点的属性。Fragment shader即片元着色器,用来改变片元的颜色,在Direct3D中称为Pixel shader,像素着色器。
1.2 编程语言
面向OpenGL的GLSL语言,Cg语言,以及面向Direct3D的HLSL语言。Cg语言与HLSL语言语法基本上相同。
1.3 Vertex shader 功能
vertex shader 可以控制如下方框中的通道对应的属性信息,包括几何变换、投影变换、光照计算等。
1.4 Fragment shader功能
Fragment shader的功能如下。
主颜色与辅助颜色(Primary Color、Secondary Color):设置辅助颜色的目的是将Specular颜色与Ambient、Diffuse颜色分开;
- 在典型的光照计算中,分别计算ambient、diffuse、specular和自发光的值,让后进行叠加;而在这之后进行纹理映射的话,specular可能会被覆盖(弱化)。
- 为了解决这个问题,OpenGL中提供了glLightModelfv(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)函数,调用函数可以将每个顶点的光照计算分为主颜色和辅助颜色,主颜色包含所有非镜面反射光照的总贡献,而辅助颜色为镜面反射光照的贡献。
- 纹理映射的时候只将主颜色和辅助颜色混合起来,执行完纹理映射后,再将主颜色和纹理颜色混合的结果与辅助颜色混合起来。
Fragment shader可以做片元测试,但实际中可以交给固定管线来做。在新版本中alpha测试需要在Frgment shader来做,固定管线已经废弃。可以使用discard来做alpha测试。
//alpha 值小于0.1f。该片元将被丢弃
if(vColorValue.a < 0.1f)
{discard;
}
1.5 vertex shader 与fragment shader案例
- vertex shader
void main(void)
{gl_Position = gl_ProjectionMatrix * gl_ModelViewMatrix * gl_vertex;
}
uniform float time;
void main(void)
{vec4 v = gl_Vertex;v.z = sin(5.0 * v.x * time ) * 0.25;gl_Position = gl_ModelViewMatrix * v;
}
- fragment shader
//改变颜色
void main(void)
{gl_FragColor = vec4(0.0,1.0,0.0,1.0);
}
2.OpenGL中的shader编程
2.1 OpenGL通过引入扩展库 glew来更方便的进行shader编程。
glew下载地址:http://glew.sourceforge.net/,对下载的源码进行编译生成lib和dll即可引用。
2.2 检测显卡是否支持shader编程
if(GLEW_ARB_vertex_shader && GLEW_ARB_fragment_shader)
{printf("Ready for glsl\n");
{
2.3 shader代码可以在C++源代码文件中存储在字符串变量中,也可将shader代码编写到独立的文件中,然后将文本文件读取到字符串中即可。
2.4 两个概念
- 着色器对象(shader):一个着色器对象对应一个shader程序;
- 着色器程序(program):可以装载多个着色器对象;
shader编程主要过程:
- 创建着色器对象;
- 将着色器源代码装载入着色器对象;
- 将源代码编译为目标代码;
- 创建着色器程序;
- 将着色器对象附加到着色器程序中;
- 链接着色器程序;
http://www.lighthouse3d.com.tutorials/glsl-tutorial/
2.5 shader编程
glUseProgram(GL_shaderProgram);
//释放
glUseProgram(0);
- 检测编译是否正确
//获取编译错误,存放到param中
glGetShaderiv(GLuint objec,GLenum type ,int* param);
type : GL_COMPILE_STATUS
- 检查链接是否正确
glGetProgramiv(GLuint objec,GLenum type ,int* param)
type : GL_LINK_STATUS
- 获取日志Infolog
glGetSHaderInfoLog(GLuint objec,int maxLen ,int* len,char* log);
glGetProgramInfoLog(GLuint objec,int maxLen ,int* len,char* log);
- 清除
glDetachShader(GLuint program,GLuint shader);
glDeleteShader(GLuint id);
glDeleteProgram(GLuint id);
3.VS与FS之间的数据流
vertex shader代码只需要编写对单个顶点的操作即可,GPU会自动将其作用到其他顶点上;fragment shader只需要编写对单个片元的操作即可。
- VS的输入:针对顶点的属性、一致型变量(uniform)(对所有顶点都一样);
- VS的输出:针对顶点的数据;
- FS的输入:针对片元的属性、一致型变量(uniform)(对所有片元都一样);
- FS的输出:gl_FragColor、gl_FragDepth 、…;
编写shader时,内建的变量以gl开头,可以直接使用。而自定义的变量,从程序中传入。
- 代码程序,如下进行time以及vertCol变量的传递,与VS中的同名变量绑定。
glUseProgram(GL_shaderProgram);
//取得shader代码中的time变量的location
time_location = glGetUniformLocation(G_shaderProgram,"time");
//将time_location与程序中定义的变量shaderTime进行关联,则shaderTime的值就可以传递到time,即可对shaderTime进行操作即可;
glUniform1f(time_location,shaderTime);//取得shader中vertCol变量的localtion
vertCol_location = glGetAttributeLocation(G_shaderProgram,"vertCol");//通过函数将值进行传递
glVertexAttrib4f(vertCol_location ,1.0f,0.0f,0.0f,0.0f);
- vertex shader程序
uniform float time;
in vec4 vertCol; // 表述输入数据
out vec4 col; //输出数据;void main(void)
{vec4 v = gl_Vertex;v.y += time * 0.1;col = vertCol;gl_Position = gl_ModelViewProjectionMatrix * v;
}
- fragment shader程序
in vec4 col; //与vertxe中col对应
void main(void)
{gl_FragColor = col;
}
4.VS/FS的输入与输出变量
4.1 可以传输给VS的数据
内建的uniform变量,如gl_ModelViewMatrix;只读类型;
内建的顶点属性变量(in 类型),如gl_Vertex;只读。
自己定义的uniform 类型变量,需要人为赋值,如下进行赋值操作。
自己定义的in类型变量,并进行赋值操作;也可以利用内建的变量来传递,如rgba中的a分量;
in vec4 vertMass;
- 纹理数据;
shader编程还是内嵌到固定流水线当中,内建变量的值还是来自固定流水线。
4.2 VS的输出
特定变量(Special Output Variables);可读可写;
内建顶点属性变量(加out限定符);可读可写;
自定义的顶点属性变量(加out限定符);
4.3 FS输入
- 内建的uniform变量;
- 内建的in类型变量;
- 其他
4.4 FS的输出
可以将缓冲数据绘制到gl_FragData,后面通过gl_FragData获取绘制到缓冲区的数据;
5.VS的out变量与FS的in变量的对应
6.总结
附录:图形编程技术,北京林业大学,杨刚
OpenGL之Shader编程入门相关推荐
- shader 编程入门(一)
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40723789 作者:毛星云(浅 ...
- Cg编程入门编(OpenGL)
Cg编程入门编(OpenGL) 原注:B Alex D'Angelo (alexz@FusionIndustries.com) 译: 华文广 未经本人同意,不能用于商业出版用途. 本文将介绍如何在 ...
- OpenGL编程入门学习
OpenGL编程入门学习 非常详细的教程,很适合初学者 本文转自:http://www.cppblog.com/doing5552/archive/2009/01/08/71532.html === ...
- 实验一OpenGL图形编程入门
实验一OpenGL图形编程入门 一. 实验目的 1.了解和掌握OpenGL的安装. 2.掌握一个简单的基于OpenGL的C++程序结构. 3.掌握Win32程序框架. 4.掌握OpenGL中若干基本图 ...
- Unity3D Shader编程】之二 雪山飞狐篇:Unity的基本Shader框架写法颜色、光照与材质
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://blog.csdn.net/poem_qianmo/article/details/40955607 作者:毛星云(浅墨) ...
- Shader Forge 入门学习(一) 基础操作
引言:失踪人口回归,最近几个月刚刚毕业,进入社会,对着未来有着些许迷茫,但起风了,唯有努力生存!近日学习Shader Forge,记录下来,共同进步!内容主要包括ShaderForge的操作设置,并配 ...
- 【浅墨Unity3D Shader编程】之三 光之城堡篇:子着色器、通道与标签的写法 amp; 纹理混合...
本系列文章由@浅墨_毛星云 出品,转载请注明出处. 文章链接: http://hpw123.net/a/C__/kongzhitaichengxu/2014/1117/120.html 作者:毛星 ...
- 游戏编程入门(1) -- 精灵 ISprite
对于游戏编程而言,我也是个初学者,这个游戏编程入门系列的文章,就当作是我在学习游戏编程的笔记和阶段小结吧.我们先从最简单的"精灵"开始,暂时我们不需要考虑DirectX或是 ...
- 【GPU精粹与Shader编程】(一) 全系列核心知识点总览
系列文章前言 <GPU Gems>1~3 .<GPU Pro>1~7 以及<GEM Zen>组成的GPU精粹系列书籍,是游戏开发.计算机图形学和渲染领域的业界大牛们 ...
最新文章
- Linux学习(十)---网络配置
- fifo 上使用 select -- 转
- 【Android 高性能音频】AAudio 音频流 构建器 ( AAudio.h | 流构造器 | 音频设备配置 | 音频采样配置 | 构建器销毁 )
- 反射load,loadfile,LoadFrom区别
- 3.3.1网络原理数据链路层之差错控制(检错编码和纠错编码)-(奇偶校验码、CRC循环冗余码、海明码)
- python可以在unix_在python窗口中使用绝对的unix路径
- ReactNative--React简介
- 快速掌握MATLAB应用,从这一步开始
- go hive skynet_云风的skynet在国内外来看究竟算什么水平?可以一统国内游戏服务端框架吗?...
- vue-cli3.0打包时如何忽略某个第三方依赖包
- LeetCode 189. Rotate Array
- 熊猫python小课靠谱吗_新的投资风向标在哪里?
- 基于WF的意见征集6(浅析)
- ffmpeg编码个参数的设置以及作用
- python做圆柱绕流_Fluent学习笔记(25)-----圆柱绕流(卡门涡街)
- HTTP性能测试工具siege
- F5 LTM ping 数据包丢包解决过程
- 简单拖拉拽就能做数据可视化分析图表
- 如何访问集群中指定的服务器,【Nacos源码之配置管理 六】集群模式下服务器之间是如何互相感知的...
- MYSQL1146解决方法