推荐日志

GLSL环境的搭建(扫盲帖)

[ 2007-01-10 12:22:59 | 作者: Admin ]
字体大小: | |
我发现很多人都会写shader,但就是不知道整个环境如何搭建,空有一些shader程序,
却没有办法在OPENGL调试运行,我当初学CG的时候也有过这样的经历,看了那么长时间
的书,却发现书上没有详细的讲解CG环境的搭建。所以本文将详细的介绍如何搭建另一种
shader语言 - GLSL的环境搭建。

下面我们将完成一个初始化shader的函数 void initShader(void)

首先保证你的工程包含了 glext.h

这个初始化的过程将分为以下几个步骤:
1、查询支持的Extensions
这一步主要是检测你的显卡是否支持sl
char *ext = (char*)glGetString( GL_EXTENSIONS );
它将返回一串支持的extensions, 我们需要的是查询。

2、查询是否支持 shader_language
 if( strstr( ext, "GL_ARB_shading_language_100" ) == NULL )
 {
 //This extension string indicates that the OpenGL Shading Language,
 // version 1.00, is supported.
 MessageBox(NULL,"GL_ARB_shading_language_100 extension was not found",
 "ERROR",MB_OK|MB_ICONEXCLAMATION);
 return;
 }

 if( strstr( ext, "GL_ARB_shader_objects" ) == NULL )
 {
 MessageBox(NULL,"GL_ARB_shader_objects extension was not found",
 "ERROR",MB_OK|MB_ICONEXCLAMATION);
 return;
 }
可见,如果不支持,我们就返回了。

3、获得函数指针
当上面查询的步骤通过了以后,我们就需要通过扩展获得GLSL操作的相关函数了。
 glCreateProgramObjectARB = (PFNGLCREATEPROGRAMOBJECTARBPROC)wglGetProcAddress("glCreateProgramObjectARB");
 glDeleteObjectARB = (PFNGLDELETEOBJECTARBPROC)wglGetProcAddress("glDeleteObjectARB");
 glUseProgramObjectARB = (PFNGLUSEPROGRAMOBJECTARBPROC)wglGetProcAddress("glUseProgramObjectARB");
 glCreateShaderObjectARB = (PFNGLCREATESHADEROBJECTARBPROC)wglGetProcAddress("glCreateShaderObjectARB");
 glShaderSourceARB = (PFNGLSHADERSOURCEARBPROC)wglGetProcAddress("glShaderSourceARB");
 glCompileShaderARB = (PFNGLCOMPILESHADERARBPROC)wglGetProcAddress("glCompileShaderARB");
 glGetObjectParameterivARB = (PFNGLGETOBJECTPARAMETERIVARBPROC)wglGetProcAddress("glGetObjectParameterivARB");
 glAttachObjectARB = (PFNGLATTACHOBJECTARBPROC)wglGetProcAddress("glAttachObjectARB");
 glGetInfoLogARB = (PFNGLGETINFOLOGARBPROC)wglGetProcAddress("glGetInfoLogARB");
 glLinkProgramARB = (PFNGLLINKPROGRAMARBPROC)wglGetProcAddress("glLinkProgramARB");
 glGetUniformLocationARB = (PFNGLGETUNIFORMLOCATIONARBPROC)wglGetProcAddress("glGetUniformLocationARB");
 glUniform4fARB = (PFNGLUNIFORM4FARBPROC)wglGetProcAddress("glUniform4fARB");
    glUniform1iARB = (PFNGLUNIFORM1IARBPROC)wglGetProcAddress("glUniform1iARB");

 if( !glCreateProgramObjectARB || !glDeleteObjectARB || !glUseProgramObjectARB ||
 !glCreateShaderObjectARB || !glCreateShaderObjectARB || !glCompileShaderARB ||
 !glGetObjectParameterivARB || !glAttachObjectARB || !glGetInfoLogARB ||
 !glLinkProgramARB || !glGetUniformLocationARB || !glUniform4fARB ||
      !glUniform1iARB )
 {
 MessageBox(NULL,"One or more GL_ARB_shader_objects functions were not found",
 "ERROR",MB_OK|MB_ICONEXCLAMATION);
 return;
 }
当然我们需要先定义以下这些全局指针
PFNGLCREATEPROGRAMOBJECTARBPROC glCreateProgramObjectARB = NULL;
PFNGLDELETEOBJECTARBPROC glDeleteObjectARB = NULL;
PFNGLUSEPROGRAMOBJECTARBPROC glUseProgramObjectARB = NULL;
PFNGLCREATESHADEROBJECTARBPROC glCreateShaderObjectARB = NULL;
PFNGLSHADERSOURCEARBPROC glShaderSourceARB = NULL;
PFNGLCOMPILESHADERARBPROC glCompileShaderARB = NULL;
PFNGLGETOBJECTPARAMETERIVARBPROC glGetObjectParameterivARB = NULL;
PFNGLATTACHOBJECTARBPROC glAttachObjectARB = NULL;
PFNGLGETINFOLOGARBPROC glGetInfoLogARB = NULL;
PFNGLLINKPROGRAMARBPROC glLinkProgramARB = NULL;
PFNGLGETUNIFORMLOCATIONARBPROC glGetUniformLocationARB = NULL;
PFNGLUNIFORM4FARBPROC glUniform4fARB = NULL;
PFNGLUNIFORM1IARBPROC glUniform1iARB = NULL;
操作GLSL的函数,当然不只这些,你可以通过你的需要,添加新的函数指针。

4、读取并编译shader程序
直接看代码,我也说不清楚了。
 const char *vertexShaderStrings[1];
 const char *fragmentShaderStrings[1];
 GLint bVertCompiled;
 GLint bFragCompiled;
 GLint bLinked;
 char str[4096];

  //
  // Create the vertex shader...
  //

 g_vertexShader = glCreateShaderObjectARB( GL_VERTEX_SHADER_ARB );

  unsigned char *vertexShaderAssembly = readShaderFile( "vertex_shader.vert" );
 vertexShaderStrings[0] = (char*)vertexShaderAssembly;
 glShaderSourceARB( g_vertexShader, 1, vertexShaderStrings, NULL );
 glCompileShaderARB( g_vertexShader);
 delete vertexShaderAssembly;

 glGetObjectParameterivARB( g_vertexShader, GL_OBJECT_COMPILE_STATUS_ARB,
 &bVertCompiled );
 if( bVertCompiled == false )
  {
    glGetInfoLogARB(g_vertexShader, sizeof(str), NULL, str);
    MessageBox( NULL, str, "Vertex Shader Compile Error", MB_OK|MB_ICONEXCLAMATION );
  }

  //
  // Create the fragment shader...
  //

 g_fragmentShader = glCreateShaderObjectARB( GL_FRAGMENT_SHADER_ARB );

 unsigned char *fragmentShaderAssembly = readShaderFile( "fragment_shader.frag" );
 fragmentShaderStrings[0] = (char*)fragmentShaderAssembly;
 glShaderSourceARB( g_fragmentShader, 1, fragmentShaderStrings, NULL );
 glCompileShaderARB( g_fragmentShader );
 delete fragmentShaderAssembly;

 glGetObjectParameterivARB( g_fragmentShader, GL_OBJECT_COMPILE_STATUS_ARB,
 &bFragCompiled );
 if( bFragCompiled == false )
  {
    glGetInfoLogARB( g_fragmentShader, sizeof(str), NULL, str );
    MessageBox( NULL, str, "Fragment Shader Compile Error", MB_OK|MB_ICONEXCLAMATION );
  }

 //
 // Create a program object and attach the two compiled shaders...
 //

 g_programObj = glCreateProgramObjectARB();
 glAttachObjectARB( g_programObj, g_vertexShader );
 glAttachObjectARB( g_programObj, g_fragmentShader );

 //
 // Link the program object and print out the info log...
 //

 glLinkProgramARB( g_programObj );
 glGetObjectParameterivARB( g_programObj, GL_OBJECT_LINK_STATUS_ARB, &bLinked );

 if( bLinked == false )
  {
    glGetInfoLogARB( g_programObj, sizeof(str), NULL, str );
    MessageBox( NULL, str, "Linking Error", MB_OK|MB_ICONEXCLAMATION );
  }

readShaderFile函数如下:
unsigned char *readShaderFile( const char *fileName )
{
 FILE *file = fopen( fileName, "r" );

 if( file == NULL )
 {
 MessageBox( NULL, "Cannot open shader file!", "ERROR",
 MB_OK | MB_ICONEXCLAMATION );
    return 0;
 }

 struct _stat fileStats;

 if( _stat( fileName, &fileStats ) != 0 )
 {
 MessageBox( NULL, "Cannot get file stats for shader file!", "ERROR",
 MB_OK | MB_ICONEXCLAMATION );
 return 0;
 }

 unsigned char *buffer = new unsigned char[fileStats.st_size];

  int bytes = fread( buffer, 1, fileStats.st_size, file );

 buffer[bytes] = 0;

  fclose( file );

  return buffer;
}

5、使用shader
glUseProgramObjectARB( g_programObj );

//DrawSometing
................................

glUseProgramObjectARB( NULL );

6、销毁shader及环境
 glDeleteObjectARB( g_vertexShader );
 glDeleteObjectARB( g_fragmentShader );
 glDeleteObjectARB( g_programObj );
评论Feed 评论Feed: http://www.azure.com.cn/feed.asp?q=comment&id=234

浏览模式: 显示全部 | 评论: 4 | 引用: 0 | 排序 | 浏览: 7379
xophiix
[ 2007-01-19 10:52:09 ]
把这些用class和namespace包装一下用起来会更方便:)
cO_olWinD
[ 2007-04-13 17:12:03 ]
好帖, 去年第一次用GLSL, 做个环境纹理映射, vs和fs文件一天就写完了, 就是不知道如何搭配环境, 英语又差,捧着一本英文的橘皮书弄了多半周才把环境搭好.
swellingflash
[ 2007-06-26 15:11:20 ]
error C2079: 'fileStats' uses undefined struct '_stat'

老大!这个错误怎么解决
swellingflash
[ 2007-06-26 15:31:51 ]
找到了,原来是sys/stat.h头文件

此日志不可发表评论.
ħ˽ ħ˽