学了接近一个月的OpenGL,最终要排上用场了...好吧,就从学到的shader(着色器)开刀吧。

先简单的介绍shader,shader事实上是显卡的功能,就是利用显卡的GPU去做图像处理的工作,而不是CPU,这样能够在一些复杂的大程序中释放CPU空间而提高效率。这篇文章仅仅是简单的介绍shader的使用,并没有介绍着色语言的语法结构等方面内容。后面等自己研究好了继续更新。

使用shader,一般要经过一下几个步骤:

1、创建shader,这里会使用到glew的拓展库,应该包括glew.h和glew32.lib。利用一下函数创建:

GLhandleARB frag_shader;
//创建fragment Shader
//--------------------------------------------------------------------
// GLuint glCreateShader(GLenum shaderType);
// 參数:
// ·shaderType – GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
//--------------------------------------------------------------------
frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

2、向shader中导入着色程序,利用一下函数:

//---------------------------------------------------------------------------------------------------------------------
//void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lenOfStrings);
//參数:
//·shader – the handler to the shader.
//·numOfStrings – the number of strings in the array.
//·strings – the array of strings.
//·lenOfStrings – an array with the length of each string, or NULL, meaning that the strings are NULL terminated.
//----------------------------------------------------------------------------------------------------------------------
glShaderSourceARB(frag_shader,1,(const char**)&inShader,NULL);

3、编译shader,就是将着色程序编译成shader能够识别的程序,以便使用:

//---------------------------------------------------------
//void glCompileShader(GLuint shader);
//參数:
//.shader – the handler to the shader.
//----------------------------------------------------------
glCompileShaderARB(frag_shader);

4、查询shader的状态,shader并不能向C/C++编译器那样能够print信息出来以參考,可是能够通过logInfo来看:

glGetObjectParameterivARB(frag_shader,GL_OBJECT_COMPILE_STATUS_ARB,&result);

if(!result)
{
char str[4096] = {0};
//------------------------------------------------------------------------------------
//将调试信息放入infoLog中
//void glGetShaderInfoLog(GLuint object, int maxLen, int *len, char *log);
//void glGetProgramInfoLog(GLuint object, int maxLen, int *len, char *log);
//參数:
//·object – the handler to the object. Either a shader or a program
//·maxLen – The maximum number of chars to retrieve from the InfoLog.
//·len – returns the actual length of the retrieved InfoLog.
//·log – The log itself.
//------------------------------------------------------------------------------
glGetInfoLogARB(frag_shader,sizeof(str),NULL,str);
glDeleteObjectARB(frag_shader);
return ;
}

5、连接shader,前面仅仅是把着色程序编译OK,如今要给创建好的shader使用:

shader = link(1,frag_shader);

6、link()函数是我自己写的,以下是link函数的代码:

GLhandleARB CShader::link(int shader_count,...)
{
//创建一个程序
GLhandleARB program = glCreateProgramObjectARB();
GLhandleARB shaderT = NULL; va_list marker; //初始化
va_start(marker,shader_count);
for(int i = 0; i< shader_count; i++)
{
shaderT = va_arg(marker,GLhandleARB);
//------------------------------------------------------------
//void glAttachShader(GLuint program, GLuint shader);
//參数:
// ·program – the handler to the program.
// ·shader – the handler to the shader you want to attach.
//-------------------------------------------------------------
glAttachObjectARB(program,shaderT);
}
va_end(marker); //连接程序
glLinkProgramARB(program); int result = 0;
glGetObjectParameterivARB(program,GL_OBJECT_LINK_STATUS_ARB,&result);
if(!result)
{
char str[4096] = {0};
glGetInfoLogARB(program,sizeof(str),NULL,str);
glDeleteObjectARB(program); return NULL;
}
return program;
}

事实上这个函数能够将多个着色程序给一个shader使用。

7、后面就是怎么使用Shader了,使用glUseProgram(program)和glUseProgram(NULL)要使用和卸载shader,

还有能够从C++代码中传递给着色程序的參数。

8、还有就是怎么把着色程序导入到shader中,这里事实上是一个纯读取文档的过程,并不难。

这里给出整个shader的程序:

CShader.h

#pragma once 

#ifndef GL_ARB_shader_objects
typedef GLhandleARB
typedef GLcharARB
#endif class CShader
{
public:
CShader(void);
public:
~CShader(void); public:
//初始化shader
void init(const char* inShader); //绑定纹理
void bind(); //撤销纹理
void unBind(); bool setParameter(char* keyword, GLfloat fv);
bool setParameter(char* keyword, GLuint texID);
char* loadShaderTex(const char* fileName); private:
GLhandleARB link(int shader_count,...);
public:
GLhandleARB shader; };

CShader.cpp

#include "stdafx.h"
#include <gl/glew.h>
#include "CShader.h"
#include <stdlib.h>
#include <stdarg.h> #pragma comment(lib,"glew32.lib") CShader::CShader(void)
{ } CShader::~CShader(void)
{ } void CShader::init(const char* inShader)
{
GLhandleARB frag_shader;
//创建fragment Shader
//--------------------------------------------------------------------
// GLuint glCreateShader(GLenum shaderType);
// 參数:
// ·shaderType – GL_VERTEX_SHADER or GL_FRAGMENT_SHADER.
//--------------------------------------------------------------------
frag_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB); //---------------------------------------------------------------------------------------------------------------------
//void glShaderSource(GLuint shader, int numOfStrings, const char **strings, int *lenOfStrings);
//參数:
// ·shader – the handler to the shader.
// ·numOfStrings – the number of strings in the array.
// ·strings – the array of strings.
// ·lenOfStrings – an array with the length of each string, or NULL, meaning that the strings are NULL terminated.
//----------------------------------------------------------------------------------------------------------------------
glShaderSourceARB(frag_shader,1,(const char**)&inShader,NULL); //---------------------------------------------------------
//void glCompileShader(GLuint shader);
//參数:
// .shader – the handler to the shader.
//----------------------------------------------------------
glCompileShaderARB(frag_shader); int result = 0;
//查询状态
glGetObjectParameterivARB(frag_shader,GL_OBJECT_COMPILE_STATUS_ARB,&result); if(!result)
{
char str[4096] = {0};
//------------------------------------------------------------------------------------
//将调试信息放入infoLog中
//void glGetShaderInfoLog(GLuint object, int maxLen, int *len, char *log);
//void glGetProgramInfoLog(GLuint object, int maxLen, int *len, char *log);
//參数:
// ·object – the handler to the object. Either a shader or a program
// ·maxLen – The maximum number of chars to retrieve from the InfoLog.
// ·len – returns the actual length of the retrieved InfoLog.
// ·log – The log itself.
//------------------------------------------------------------------------------
glGetInfoLogARB(frag_shader,sizeof(str),NULL,str);
glDeleteObjectARB(frag_shader);
return ;
}
//Compile shader
shader = link(1,frag_shader);
glDeleteObjectARB(frag_shader);
} GLhandleARB CShader::link(int shader_count,...)
{
//创建一个程序
GLhandleARB program = glCreateProgramObjectARB();
GLhandleARB shaderT = NULL; va_list marker; //初始化
va_start(marker,shader_count);
for(int i = 0; i< shader_count; i++)
{
shaderT = va_arg(marker,GLhandleARB);
//------------------------------------------------------------
//void glAttachShader(GLuint program, GLuint shader);
//參数:
// ·program – the handler to the program.
// ·shader – the handler to the shader you want to attach.
//-------------------------------------------------------------
glAttachObjectARB(program,shaderT);
}
va_end(marker); //连接程序
glLinkProgramARB(program); int result = 0;
glGetObjectParameterivARB(program,GL_OBJECT_LINK_STATUS_ARB,&result);
if(!result)
{
char str[4096] = {0};
glGetInfoLogARB(program,sizeof(str),NULL,str);
glDeleteObjectARB(program); return NULL;
}
return program;
} void CShader::bind()
{
//if shader link successfully,then use it
glUseProgram( shader);
}
bool CShader::setParameter(char* keyword,GLfloat fv)
{
//find out where the flicker constant lives
GLint ret = glGetUniformLocation(shader, keyword);
if(ret != -1)
{
glUniform1f(ret,fv);
return true;
}
return false;
} bool CShader::setParameter(char* keyword,GLuint texID)
{
//Find out where the flicker constant lives
GLint ret = glGetUniformLocation(shader,keyword); if(ret != -1)
{
glUniform1iARB(ret, texID);
return true;
}
return false;
} void CShader::unBind()
{
glUseProgramObjectARB(NULL);
} char* CShader::loadShaderTex(const char* fileName)
{
char* shaderText = NULL;
GLint shaderLength = 0;
FILE *fp; fp = fopen(fileName,"r");
if(fp != NULL)
{
//get the char length
while(fgetc(fp) != EOF)
{
shaderLength++;
}
rewind(fp); shaderText = (GLchar*)malloc(shaderLength);
if(shaderText != NULL)
{
fread(shaderText,1,shaderLength,fp);
}
shaderText[shaderLength] = '\0';
fclose(fp);
}
return shaderText;
}

上面有把shader仅仅用写成接口,并没有给出着色程序的代码,你须要将着色程序保存为文本文档,然后用loadShaderText()读取程序,然后就是init(),利用setParameter()设置好參数就能够了。

OpenGL中shader使用的更多相关文章

  1. OpenGL中shader读取实现

    1.需要shader在OpenGL中工作,必须经过如下过程 2.代码实现 /********** * loadshader.h **********/ #pragma once #define _CR ...

  2. GLSL 在OpenGL中向shader传递信息【转】

    http://blog.csdn.net/hgl868/article/details/7872219 引言 一个OpenGL程序可以用多种方式和shader通信.注意这种通信是单向的,因为shade ...

  3. 【GLSL教程】(三)在OpenGL中向shader传递信息 【转】

    http://blog.csdn.net/racehorse/article/details/6634830 引言 一个OpenGL程序可以用多种方式和shader通信.注意这种通信是单向的,因为sh ...

  4. 【OpenGL】Shader实例分析(九)- AngryBots中的主角受伤特效

    转发请保持地址:http://blog.csdn.net/stalendp/article/details/40859441 AngryBots是Unity官方的一个非常棒的样例.非常有研究价值. 曾 ...

  5. Modern OpenGL用Shader拾取VBO内单一图元的思路和实现

    Modern OpenGL用Shader拾取VBO内单一图元的思路和实现 什么意思? 拾取 最简单的理解拾取的方式大概是到(http://www.yakergong.net/nehe/course/t ...

  6. Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(2)

    Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(2) 上一篇里介绍了Color-Coded Picking的思路和最基本的实现.在处理GL_POINTS时已经没有问题,但是处 ...

  7. Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3)

    Modern OpenGL用Shader拾取VBO内单一图元的思路和实现(3) 到上一篇为止,拾取一个VBO里的单个图元的问题已经彻底解决了.那么来看下一个问题:一个场景里可能会有多个VBO,此时每个 ...

  8. CSharpGL(6)在OpenGL中绘制UI元素

    CSharpGL(6)在OpenGL中绘制UI元素 2016-08-13 由于CSharpGL一直在更新,现在这个教程已经不适用最新的代码了.CSharpGL源码中包含10多个独立的Demo,更适合入 ...

  9. OpenGL中glVertex、显示列表(glCallList)、顶点数组(Vertex array)、VBO及VAO区别

    OpenGL中glVertex.显示列表(glCallList).顶点数组(Vertex array).VBO及VAO区别 1.glVertex 最原始的设置顶点方法,在glBegin和glEnd之间 ...

随机推荐

  1. 在Java中怎样逐行地写文件?

    下边是写东西到一个文件里的Java代码. 执行后每一次,一个新的文件被创建,而且之前一个也将会被新的文件替代.这和给文件追加内容是不同的. public static void writeFile1( ...

  2. Cocos2d-X研究之v3.x瓦片地图具体解释

    在游戏开发过程中,我们会遇到超过屏幕大小的地图,比如即时战略游戏,使得玩家能够在地图中滚动游戏画面.这类游戏一般会有丰富的背景元素,假设直接使用背景图切换的方式,须要为每一个不同的场景准备一张背景图, ...

  3. Balsamiq Mockups注册码

    Name: personalKey: eJzzzU/OLi0odswsqilILSrOz0vMqbFEAjXONYY1fu6ufgA/CA4X Name: helloWorldKey: eJzzzU/ ...

  4. 简单工厂 VS 工厂方法 VS 抽象工厂

    说到设计模式.自然少不了简单工厂模式.工厂方法和抽象工厂这三姐妹. 它们之间可谓是各有所长,术业专攻啊!这篇博客来简单的梳理一下三者之间的关系. 那么工厂又是什么意思呢?结合三者的特点,我觉得能够这样 ...

  5. 设备Oracle当误差:环境不符合要求》》解决方法

    一旦安装Oracle当我常常会遇到这样的问题.也没太在意,改了一下client\stage\cvu文件夹cvu_prereq.xml档(添加支持目前的操作系统信息)为了克服,我没有做笔记,但后来有同学 ...

  6. Linux下 目录 压缩 解压缩 打包

    http://blog.sina.com.cn/s/blog_7479f7990100zwkp.html tar -zcvf /home/xahot.tar.gz /xahot    tar -zcv ...

  7. vultr centos x64 6.5.x 升级php7.0

    升级前,先卸载 php5.6.x 卸载php5.6.2 从cent 6.5.x 需要卸载: yum remove php56u-mysqlnd-5.6.20-1.ius.centos6.x86_64 ...

  8. Nginx Rewrite规则记录

    Rewrite 是一种服务器的重写脉冲技术,它可以使得服务器可以支持 URL 重写,是一种最新流行的服务器技术.它还可以实现限制特定IP访问网站的功能.很多情况下,某个 IP 的访问很容易造成 CPU ...

  9. Android_declare-styleable_自己定义控件的属性

    1.简单实例 (1).在res/values文件下定义一个attrs.xml文件 <? xml version="1.0" encoding="utf-8" ...

  10. 为什么android你用的越多,速度较慢的手机

    依据第三方的调研数据显示,有 77% 的 Android 手机用户承认自己曾遭遇过手机变慢的影响,百度搜索"Android+ 卡慢",也有超过 460 万条结果. 在业内.Andr ...