OpenGL 入门3

来源:互联网 发布:电子口岸数据分中心 编辑:程序博客网 时间:2024/05/17 12:06

原帖地址:
http://blog.csdn.net/cordova/article/details/52495077
http://ogldev.atspace.co.uk/www/tutorial04/tutorial04.html

shader

shaders是当前的做3D图形渲染的主要方式。在之前固定管线渲染那会儿,可能我们只需要设置几个参数就能使用的渲染功能,现在需要开发者用shader自己去实现。有可能大伙儿会觉得这是自找麻烦,确实是麻烦了,不过却极大的提高了渲染的灵活性。

可编程渲染管线

这里写图片描述

Vertex Processor

对于每一个通过vertex processor的顶点,都是会被顶点shader处理的(穿进去的顶点数量是由drawcall决定的)。vertex shader不用关心图元信息。此外,不能在vertex shader中丢弃顶点,每一个进来的顶点都会被处理,并且被送出。

Geometry processor

我们会把图元信息以及相邻顶点信息提供给geometry processor。也就是说除了顶点信息之外,还有其他的信息。geometry shader能够将draw call中设定的拓扑结构改成另外一种。比如说我们传给draw call的是一个point-list的拓扑结构选项,然后通过geometry processor我们可以让他输出triangle-strip的拓扑结构来。也可以通过geometry processor来生成若干个点用于生成设定的不同的拓扑结构图形。

clipper

这个阶段的主要作用是将图元规格化到一个单位的盒子里面。同时这个阶段也会裁切远近平面之外的图元。如果顶点通过了这个阶段,那么这些顶点就会映射到屏幕坐标系中,这之后就根据他们的拓扑结构,将他们光栅化到屏幕上显示。
这三个阶段都是可选的,如果不使用shader的话,就会执行默认的设置。

API

GLuint ShaderProgram = glCreateProgram();

创建一个shaderProgram对象,所有的shader对象都会链接到这个上面。

GLuint ShaderObj = glCreateShader(ShaderType);

创建一个shader对象。shader的类型:GL_VERTEX_SHADER,GL_FRAGMENT_SHADER等。

const GLchar* p[1];p[0] = pShaderText;GLint Lengths[1];Lengths[0]= strlen(pShaderText);glShaderSource(ShaderObj, 1, p, Lengths);

将shader源码加载近shader对象之中。1标明我们有一个shader文本资源,p指向shader的字符串数组,lengths表明此字符串数组的长度。

GLint success;glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);if (!success) {GLchar InfoLog[1024];glGetShaderInfoLog(ShaderObj, sizeof(InfoLog), NULL, InfoLog);fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);}

加载完源码之后就可以编译了。当然有可能会编译失败,失败了就通过glGetShaderInfoLog来输出log信息,即可查找出错的地方。

glAttachShader(ShaderProgram, ShaderObj);

然后就可以将这个shader对象捆绑到shaderprogram对象上了。

glLinkProgram(ShaderProgram);glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);if (Success == 0) {glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);}

这之后就可以链接这个shaderprogram了,链接好了之后进行下一步。

glValidateProgram(ShaderProgram);

我们还需要使用这行代码的原因是:glLinkProgram只是检测代码有没有错误,而这个函数是检测在当前的opengl状态下,这个shaderprogram是否可以运行。对于一个有很多状态切换或者很多shader的复杂程序来说,每个drawcall之前都glValidateProgram是一个好的做法。不过在最终的程序里,没有必要这么做,因为这会损失性能,我们只在开发期间这样做就行了。

glUseProgram(ShaderProgram);

然后就可以愉快的使用这个shaderprogram了。这个shaderprogram将会一直有效,直到您替换了这个shaderprogram,或者说使用NULL去调用glUseProgram()。如果创建的shader只有可编程渲染管线的某一个阶段,那么其他的阶段将使用默认值。

简单GLSL的写法

#version 330 

这句代码说明的是GLSL的版本,如果编译器不支持这个版本,那么这个将报错。

layout (location = 0) in vec3 Position;

这句vertex shader中的代码是说,我们会将索引为0的AttribPointer筛选出来的数据当作有3个元素构成的位置向量处理。

void main()

这个是shader的入口函数。

gl_Position = vec4(0.5 * Position.x, 0.5 * Position.y, Position.z, 1.0);

gl_Position是特殊的内置变量,光栅器将会把gl_Position中存储的值当作屏幕空间中的位置信息进行处理。这句shader语句的意思是,我们将传入的顶点坐标的x,y坐标缩小到原来的一半。

out vec4 FragColor;

这句代码表示fragment shader的输出是一个颜色信息。fragment shader可以改变像素的颜色也可以改变像素点的Z值(进而确定他是否能通过深度测试)。

FragColor = vec4(1.0, 0.0, 0.0, 1.0);

定义输出的像素颜色是红色。

0 0
原创粉丝点击