zoukankan      html  css  js  c++  java
  • OpenGL中shader使用


           学了接近一个月的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()设置好参数就可以了。




     

     

  • 相关阅读:
    Java数据类型与运算符
    [DEBUG] Springboot打包jar/war后访问包外的路径
    Html大段文本自适应换行显示-SSM
    [DEBUG] ubuntu pip安装成功却无法import
    [DEBUG] ubuntu mysql root@localhost改了密码还是进不去ERROR 1698 (28000)
    [DEBUG] Spring boot前端html无法下载示例文件
    [DEBUG] spring boot在eclipse中用maven打包成jar访问templates报500错误
    [DEBUG] java中用Runtime调用python 简单程序输出null
    SpringBoot中service注入失败(A component required a bean of type 'XXService' that could not found)
    Numpy安装报错:试过N种安装方法终于
  • 原文地址:https://www.cnblogs.com/leven20061001/p/2724693.html
Copyright © 2011-2022 走看看