OpenGL着色器程序解析--初识着色器

来源:互联网 发布:卖家淘宝客怎么玩 编辑:程序博客网 时间:2024/06/06 02:49

OpenGL的版本已经从1994年的1.0版本发展到了现在的4.6版本,OpenGL早已发生了质的变迁,我们现在抛开以前的固定管线来谈谈渲染管线,即着色器的使用。
在这里我们使用的代码都来自于《OpenGL编程指南(第八版)》,由于网络上各种资源已经非常丰富(源码http://www.opengl-redbook.com/,教材https://yq.aliyun.com/articles/212785?spm=5176.100239.blogcont212917.14.EZWxCF),我们后面的文章都已代码解析为主,方便大家更轻松地去理解着色器的使用。
下面我们来看一个简单的着色器程序。在这个程序中我们第一次使用GLFW(OpenGL for windows)库,这个库是用来处理窗口命令的,可以代替glut库,可移植性更高。此外,我们还使用了GL3W库,GL3W可以简化获取函数地址的过程,并且包含了可以跨平台使用的其他一些OpenGL编程方法。如果没有GL3W,我们可能还需要执行相当多的工作才能够运行程序。

//////////////////////////////////////////////////////////////////////////////////  Triangles.cpp////////////////////////////////////////////////////////////////////////////////#include "vgl.h"#include "LoadShaders.h"enum VAO_IDs { Triangles, NumVAOs };enum Buffer_IDs { ArrayBuffer, NumBuffers };enum Attrib_IDs { vPosition = 0 };GLuint  VAOs[NumVAOs];GLuint  Buffers[NumBuffers];const GLuint  NumVertices = 6;//----------------------------------------------------------------------------//// init//voidinit( void ){    glGenVertexArrays( NumVAOs, VAOs );//初始化顶点数组名字栈,栈数组为VAOs,数组大小为NumVAOs    glBindVertexArray( VAOs[Triangles] );//创建并且绑定了一个顶点数组对象,OpenGL内部会将它作为当前对象,即所有后继的操作都会作用于这个被绑定的对象    GLfloat  vertices[NumVertices][2] = {        { -0.90f, -0.90f }, {  0.85f, -0.90f }, { -0.90f,  0.85f },  // Triangle 1        {  0.90f, -0.85f }, {  0.90f,  0.90f }, { -0.85f,  0.90f }   // Triangle 2    };    glGenBuffers( NumBuffers, Buffers );//初始化缓存名字栈,栈数组为Buffers,数组大小为NumBuffers    glBindBuffer( GL_ARRAY_BUFFER, Buffers[ArrayBuffer] );//创建并且绑定了一个缓存对象,OpenGL内部会将它作为当前对象,即所有后继的操作都会作用于这个被绑定的对象;GL_ARRAY_BUFFER为缓存类型,Buffers[ArrayBuffer]设置的是要绑定的缓存对象名称    glBufferStorage( GL_ARRAY_BUFFER, sizeof(vertices), vertices, 0);//在OpenGL服务端内存中分配size个存储单元(通常为字节),用于存储数据或者索引    ShaderInfo  shaders[] =    {//每一个OpenGL程序进行绘制的时候,都需要指定至少两个着色器:顶点着色器和片元着色器        { GL_VERTEX_SHADER, "media/shaders/triangles/triangles.vert" },        { GL_FRAGMENT_SHADER, "media/shaders/triangles/triangles.frag" },        { GL_NONE, NULL }    };    GLuint program = LoadShaders( shaders );//指定着色器    glUseProgram( program );//使用shader    /*最后的两个函数指定了顶点着色器的变量与我们存储在缓存对象中数据的关系。这也就是我们所说的着色管线装配的过程,即将应用程序与着色器之间,以及不同着色阶段之间的数据通道连接起来*/    glVertexAttribPointer( vPosition, 2, GL_FLOAT,                           GL_FALSE, 0, BUFFER_OFFSET(0) );//将着色器中声明的in变量用glVertexAttribPointer()将它关联到一个顶点属性数组vPosition,每个顶点分量为2,数据类型为浮点型。    glEnableVertexAttribArray( vPosition );//启用顶点属性数组}//----------------------------------------------------------------------------//// display//voiddisplay( void ){    static const float black[] = { 0.0f, 0.0f, 0.0f, 0.0f };    glClearBufferfv(GL_COLOR, 0, black);//清除颜色帧缓存的数据,设置背景色为黑色    glBindVertexArray( VAOs[Triangles] );    glDrawArrays( GL_TRIANGLES, 0, NumVertices );//实现顶点数据向OpenGL管线的传输,构建图元的类型为GL_TRIANGLES,绘制点从0到5}//----------------------------------------------------------------------------//// main//#ifdef _WIN32int CALLBACK WinMain(  _In_ HINSTANCE hInstance,  _In_ HINSTANCE hPrevInstance,  _In_ LPSTR     lpCmdLine,  _In_ int       nCmdShow)#elseintmain( int argc, char** argv )#endif{    glfwInit();//负责初始化GLFW库    GLFWwindow* window = glfwCreateWindow(800, 600, "Triangles", NULL, NULL);//设置了程序所使用的窗口类型以及期望的窗口尺寸,创建了一个与窗口关联的OpenGL设备环境    glfwMakeContextCurrent(window);//设置它为当前环境    gl3wInit();//初始化另一个辅助库GL3W    init();    while (!glfwWindowShouldClose(window))//判断是否需要关闭窗口    {        display();        glfwSwapBuffers(window);//重绘它的内容,并且展现给最终用户        glfwPollEvents();//检查操作系统返回的任何信息    }    glfwDestroyWindow(window);//清理窗口    glfwTerminate();//关闭GLFW库}

我们再来看看着色器文件中的内容。着色器就是使用OpenGL着色语言(OpenGL Shading Language,GLSL),该语言类似与c语言。
顶点着色器”media/shaders/triangles/triangles.vert”

#version 400 core//指定了我们所用的OpenGL着色语言的版本,即OpenGL4.0对应的glsl版本layout( location = 0 ) in vec4 vPosition;//传入GLSL的四维浮点数向量数据vPositionvoidmain(){    gl_Position = vPosition;//将输入的顶点位置复制到顶点着色器的指定输出位置gl_Position中}

片元着色器”media/shaders/triangles/triangles.frag”

#version 450 coreout vec4 fColor;//着色器输出数据void main(){    fColor = vec4(0.5, 0.4, 0.8, 1.0);}
原创粉丝点击