GLSL入门源码(1)

本例子选自OpenGL Shading Language中的第一个Shader例子,使用颜色平滑地表示一个表面的温度。温度及其颜色的范围在应用程序中进行设置。 
//先看顶点着色器temp.vert: 
uniform float CoolestTemp; 
uniform float TempRange; 
attribute float VertexTemp;//每个定点都对应一个温度值 
varying float Temperature;//传递到片段处理器进行后续处理 
void main(void) 
{
 //进行插值
Temperature = (VertexTemp - CoolestTemp) / TempRange; 
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; 
}
//片段着色器temp.frag: 
uniform vec3 CoolestColor; 
uniform vec3 HottestColor;
varying float Temperature; 
void main(void) 

//通过温度值寻找一个相应的颜色,位于最冷和最热之间 
vec3 color = mix(CoolestColor, HottestColor,Temperature); 
gl_FragColor = vec4(color,1.0); 

下面看看如何将着色器和应用程序进行链接(第一步是创建着色器对象,指定着色器源代码,进行编译,并程序对象和着色器进行绑定和链接),同时指定了一些一致变量的值 
/*public*/ 
int installShaders(const GLchar *Vertex, const GLchar *Fragment) 

GLint vertCompiled, fragCompiled; 
// status values 
GLint linked;
// Create a vertex shader object and a fragment shader object 
VertexShaderObject = glCreateShader(GL_VERTEX_SHADER); 
FragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER); /
/ Load source code strings into shaders 
glShaderSource(VertexShaderObject, 1, &Vertex, NULL); 
glShaderSource(FragmentShaderObject, 1, &Fragment, NULL); 
// Compile the brick vertex shader, and print out 
// the compiler log file. 
glCompileShader(VertexShaderObject); 
glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, &vertCompiled); 
// Compile the brick vertex shader, and print out 
// the compiler log file. 
glCompileShader(FragmentShaderObject); 
glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, &fragCompiled); 
if (!vertCompiled || !fragCompiled) 
return 0; 
// Create a program object and attach the two compiled shaders 
ProgramObject = glCreateProgram(); 
glAttachShader(ProgramObject, VertexShaderObject); 
glAttachShader(ProgramObject, FragmentShaderObject); 
// Link the program object and print out the info log 
glLinkProgram(ProgramObject); 
glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked); 
if (!linked) 
return 0; 
// Install program object as part of current state 
glUseProgram(ProgramObject); 
// Set up initial uniform values 
glUniform1f(glGetUniformLocation(ProgramObject, "CoolestTemp"), 0.0f); 
glUniform1f(glGetUniformLocation(ProgramObject, "TempRange"), 1.0f); 
glUniform3f(glGetUniformLocation(ProgramObject, "CoolestColor"), 0.0, 0.0, 1.0); 
glUniform3f(glGetUniformLocation(ProgramObject, "HottestColor"), 1.0, 0.0, 0.0); 
return 1; 

这其中用到了一些读取外部着色器代码的函数,顶点着色器后缀自定义为.vert,片段着色器自定义为.frag,我们也可以将着色器放在程序中存储在一个字符串中。 

static int readShader(char *fileName, EShaderType shaderType, char *shaderText, int size) 

// Reads a shader from the supplied file and returns the shader in the 
// arrays passed in. 
Returns 1 if successful, 0 if an error occurred. 
// The parameter size is an upper limit of the amount of bytes to read. 
// It is ok for it to be too big.
FILE *fh; 
char name[100]; 
int count; 
strcpy(name, fileName); 
switch (shaderType) 

case EVertexShader: 
strcat(name, ".vert"); 
break; 
case EFragmentShader: 
strcat(name, ".frag"); 
break; 
default: 
printf("ERROR: unknown shader file type\n"); 
exit(1); 
break; 

// Open the file 
fh = fopen(name, "r"); 
if (!fh) 
return -1; 
// Get the shader from a file. 
fseek(fh, 0, SEEK_SET); 
count = (int) fread(shaderText, 1, size, fh); 
shaderText[count] = '\0'; 
if (ferror(fh)) 
count = 0; 
fclose(fh); 
return count; 
}

/*public*/ 
int readShaderSource(char *fileName, GLchar **vertexShader, GLchar **fragmentShader) 

int vSize, fSize; 
// // Allocate memory to hold the source of our shaders. 
vSize = shaderSize(fileName, EVertexShader); 
fSize = shaderSize(fileName, EFragmentShader); 
if ((vSize == -1) || (fSize == -1)) 

printf("Cannot determine size of the shader %s\n", fileName); return 0; 

*vertexShader = (GLchar *) malloc(vSize); 
*fragmentShader = (GLchar *) malloc(fSize); 
// // Read the source code // 
if (!readShader(fileName, EVertexShader, *vertexShader, vSize)) 

printf("Cannot read the file %s.vert\n", fileName); 
return 0; 

if (!readShader(fileName, EFragmentShader, *fragmentShader, fSize)) 

printf("Cannot read the file %s.frag\n", fileName); 
return 0; 

return 1; 

这里我们只绘制一个简单的三角形,需要为每个顶点指定一个属性值,代表其温度值,着色器中我们对其进行了读取并插值。对于复杂的图形,应当使用顶点数组进行指定。 
static void display(void) 

glLoadIdentity(); 
glTranslatef(0.0, 0.0, -5.0); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//查询定点着色器属性变量VertexTemp,并对它进行设置,每个定点需要指定一个属性 
GLint tempLoc = glGetAttribLocationARB(ProgramObject, "VertexTemp"); 
glBegin(GL_TRIANGLES); 
glVertexAttrib1f(tempLoc, 0.0f); 
glVertex3f(1.0f,0.0f,0.0f); 
glVertexAttrib1f(tempLoc, 0.5f); 
glVertex3f(-1.0f,0.0f,0.0f); 
glVertexAttrib1f(tempLoc, 1.0f); 
glVertex3f(0.0f,1.0f,0.0f); 
glEnd(); 
glFlush(); 
glutSwapBuffers(); 

运行效果如下:

   
整个程序如下: 
 

#include
#include
#include
#include
#include
#define  GLEW_STATIC 1
#include
#include
#include
 
// 窗口句柄
static  GLint window;
 
GLuint ProgramObject = 0;                             // 程序对象
GLuint VertexShaderObject = 0;                    // 顶点着色器对象
GLuint FragmentShaderObject = 0;     // 片段着色器对象
 
//Shader 类型
typedef  enum {
    EVertexShader,
         EFragmentShader,
} EShaderType;
 
// 用来检查 OpenGL 版本,需要 GLSL 2.0 支持
void  getGlVersion(  int  *major,  int  *minor )
{
     const char * verstr = ( const char *)glGetString( GL_VERSION );
     if ( (verstr == NULL) || (sscanf( verstr,  "%d.%d" , major, minor ) != 2) )
    {
        *major = *minor = 0;
        fprintf( stderr,  "Invalid GL_VERSION format!!!\n"  );
    }
}
 
static void  display( void )
{
    glLoadIdentity();
    glTranslatef(0.0, 0.0, -5.0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 
          // 查询定点着色器属性变量 VertexTemp ,并对它进行设置,每个定点需要指定一个属性
         GLint tempLoc = glGetAttribLocationARB(ProgramObject,  "VertexTemp" );
         glBegin(GL_TRIANGLES);
                   glVertexAttrib1f(tempLoc, 0.0f);        
                   glVertex3f(1.0f,0.0f,0.0f);
                   glVertexAttrib1f(tempLoc, 0.5f);
                   glVertex3f(-1.0f,0.0f,0.0f);
                   glVertexAttrib1f(tempLoc, 1.0f);
                   glVertex3f(0.0f,1.0f,0.0f);
         glEnd();
    glFlush();
    glutSwapBuffers();
}
 
static void  reshape( int  wid,  int  ht)
{
     float  vp = 0.8f;
     float  aspect = ( float ) wid / ( float ) ht;
        
    glViewport(0, 0, wid, ht);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
     //glOrtho(-1.0, 1.0, -1.0, 1.0, -10.0, 10.0);
    glFrustum(-vp, vp, -vp / aspect, vp / aspect, 3, 10.0);
         glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
}
 
 
//Shader related functions
static int  shaderSize( char  *fileName, EShaderType shaderType)
{
          // 返回顶点着色器或者片段着色器的大小
     char  name[100];
    strcpy(name, fileName);
 
     switch  (shaderType)
    {
         case  EVertexShader:
            strcat(name,  ".vert" );
             break ;
         case  EFragmentShader:
            strcat(name,  ".frag" );
             break ;
         default :
            printf( "ERROR: unknown shader file type\n" );
            exit(1);
             break ;
    }
 
     int  count = -1;
     // Open the file, seek to the end to find its length
     int  fd = _open(name, _O_RDONLY);
     if  (fd != -1)
    {
        count = _lseek(fd, 0, SEEK_END) + 1;
        _close(fd);
    }
     return  count;
}
 
 
static int  readShader( char  *fileName, EShaderType shaderType,  char  *shaderText,  int  size)
{
     //
     // Reads a shader from the supplied file and returns the shader in the
     // arrays passed in. Returns 1 if successful, 0 if an error occurred.
     // The parameter size is an upper limit of the amount of bytes to read.
     // It is ok for it to be too big.
     //
    FILE *fh;
     char  name[100];
     int  count;
 
    strcpy(name, fileName);
 
     switch  (shaderType)
    {
         case  EVertexShader:
            strcat(name,  ".vert" );
             break ;
         case  EFragmentShader:
            strcat(name,  ".frag" );
             break ;
         default :
            printf( "ERROR: unknown shader file type\n" );
            exit(1);
             break ;
    }
 
     // Open the file
    fh = fopen(name,  "r" );
     if  (!fh)
         return  -1;
 
     // Get the shader from a file.
    fseek(fh, 0, SEEK_SET);
    count = ( int ) fread(shaderText, 1, size, fh);
    shaderText[count] =  '\0' ;
 
     if  (ferror(fh))
        count = 0;
 
    fclose(fh);
     return  count;
}
 
 
/*public*/
int  readShaderSource( char  *fileName, GLchar **vertexShader, GLchar **fragmentShader)
{
     int  vSize, fSize;
 
     //
     // Allocate memory to hold the source of our shaders.
     //
    vSize = shaderSize(fileName, EVertexShader);
    fSize = shaderSize(fileName, EFragmentShader);
 
     if  ((vSize == -1) || (fSize == -1))
    {
        printf( "Cannot determine size of the shader %s\n" , fileName);
         return  0;
    }
 
    *vertexShader = (GLchar *) malloc(vSize);
    *fragmentShader = (GLchar *) malloc(fSize);
 
     //
     // Read the source code
     //
     if  (!readShader(fileName, EVertexShader, *vertexShader, vSize))
    {
        printf( "Cannot read the file %s.vert\n" , fileName);
         return  0;
    }
 
     if  (!readShader(fileName, EFragmentShader, *fragmentShader, fSize))
    {
        printf( "Cannot read the file %s.frag\n" , fileName);
         return  0;
    }
 
     return  1;
}
 
 
/*public*/
int  installShaders( const  GLchar *Vertex,
                         const  GLchar *Fragment)
{
    GLint vertCompiled, fragCompiled;     // status values
    GLint linked;
 
     // Create a vertex shader object and a fragment shader object
 
    VertexShaderObject = glCreateShader(GL_VERTEX_SHADER);
    FragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);
 
     // Load source code strings into shaders
 
    glShaderSource(VertexShaderObject, 1, &Vertex, NULL);
    glShaderSource(FragmentShaderObject, 1, &Fragment, NULL);
 
     // Compile the brick vertex shader, and print out
     // the compiler log file.
 
    glCompileShader(VertexShaderObject);
    glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, &vertCompiled);
 
     // Compile the brick vertex shader, and print out
     // the compiler log file.
 
    glCompileShader(FragmentShaderObject);
    glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, &fragCompiled);
 
     if  (!vertCompiled || !fragCompiled)
         return  0;
 
     // Create a program object and attach the two compiled shaders
 
    ProgramObject = glCreateProgram();
    glAttachShader(ProgramObject, VertexShaderObject);
    glAttachShader(ProgramObject, FragmentShaderObject);
 
     // Link the program object and print out the info log
 
    glLinkProgram(ProgramObject);
    glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked);
 
     if  (!linked)
         return  0;
 
     // Install program object as part of current state
 
    glUseProgram(ProgramObject);
 
     // Set up initial uniform values
    glUniform1f(glGetUniformLocation(ProgramObject,  "CoolestTemp" ), 0.0f);
    glUniform1f(glGetUniformLocation(ProgramObject,  "TempRange" ), 1.0f);
    glUniform3f(glGetUniformLocation(ProgramObject,  "CoolestColor" ), 0.0, 0.0, 1.0);
    glUniform3f(glGetUniformLocation(ProgramObject,  "HottestColor" ), 1.0, 0.0, 0.0);
 
     return  1;
}
 
/******************************************************************************/
/*
/* Main
/*
/******************************************************************************/
int  main(  int  argc,  char  **argv )
{
     int  success = 0;
     int  gl_major, gl_minor;
    GLchar *VertexShaderSource, *FragmentShaderSource;
        
    glutInit( &argc, argv );
    glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);
    glutInitWindowSize(500, 500);
    window = glutCreateWindow(  "Temperature Shader" );
        
    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
        
     // Initialize the "OpenGL Extension Wrangler" library
    glewInit();
        
     // Make sure that OpenGL 2.0 is supported by the driver
    getGlVersion(&gl_major, &gl_minor);
    printf( "GL_VERSION major=%d minor=%d\n" , gl_major, gl_minor);
        
     if  (gl_major < 2)
    {
        printf( "GL_VERSION major=%d minor=%d\n" , gl_major, gl_minor);
        printf( "Support for OpenGL 2.0 is required for this demo...exiting\n" );
        exit(1);
    }
        
    readShaderSource( "temp" , &VertexShaderSource, &FragmentShaderSource);
    success = installShaders(VertexShaderSource, FragmentShaderSource);
        
     if  (success)
        glutMainLoop();
   
     return  0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
05-31
GLSL(OpenGL Shading Language)是一种用于编写OpenGL程序的编程语言,它是一种基于C语言的高级着色器语言,用于编写GPU上的着色器程序。GLSL主要用于OpenGL、OpenGL ES和WebGL等图形库中,通过编写着色器程序来实现各种图形效果,如光照、阴影、反射等。 GLSL支持多种数据类型,包括标量(float)、向量(vec2、vec3、vec4)、矩阵(mat2、mat3、mat4)和纹理(sampler2D、samplerCube)等。GLSL还提供了许多内置函数,如向量运算、矩阵运算、数学运算、纹理采样等,以及流程控制语句,如if、for、while等。 GLSL中的着色器程序包括顶点着色器、片元着色器和几何着色器等,其中顶点着色器主要用于处理顶点数据,片元着色器主要用于处理像素数据,几何着色器主要用于处理几何图形数据。通过编写GLSL着色器程序,可以实现各种图像效果,如模糊、反锯齿、色彩调整、光照计算等。 以下是一个简单的GLSL片元着色器程序示例,用于将颜色值反转: ```glsl #version 330 core in vec2 TexCoord; out vec4 FragColor; uniform sampler2D texture1; void main() { vec4 color = texture(texture1, TexCoord); color.rgb = 1.0 - color.rgb; FragColor = color; } ``` 在上面的代码中,`in`表示输变量,`out`表示输出变量,`uniform`表示全局变量,`sampler2D`表示二维纹理变量。`main()`函数是GLSL程序的主函数,用于处理每个像素的颜色。`texture()`函数用于从纹理中获取颜色值,`1.0 - color.rgb`表示将颜色值反转。`FragColor`是输出变量,表示当前像素的颜色值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值