天天看點

linux下glew例子,一個簡單的GLSL Shader例子

本例子選自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);

}

下面看看如何将着色器和應用程式進行連結(第一步是建立着色器對象,指定着色器源代碼,進行編譯,并程式對象和着色器進行綁定和連結),同時指定了一些一緻變量的值

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,我們也可以将着色器放在程式中存儲在一個字元串中。

//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;

}

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();

}

運作效果如下:

linux下glew例子,一個簡單的GLSL Shader例子

整個程式如下:

#include

#include

#include

#include

#include

#defineGLEW_STATIC 1

#include

#include

#include

//視窗句柄

staticGLint window;

GLuint ProgramObject = 0;//程式對象

GLuint VertexShaderObject = 0;//頂點着色器對象

GLuint FragmentShaderObject = 0;//片段着色器對象

//Shader類型

typedefenum {

EVertexShader,

EFragmentShader,

} EShaderType;

//用來檢查OpenGL版本,需要GLSL 2.0支援

voidgetGlVersion(int*major,int*minor )

{

constchar* verstr = (constchar*)glGetString( GL_VERSION );

if( (verstr == NULL) || (sscanf( verstr,"%d.%d", major, minor ) != 2) )

{

*major = *minor = 0;

fprintf( stderr,"Invalid GL_VERSION format!!!\n");

}

}

staticvoiddisplay(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();

}

staticvoidreshape(intwid,intht)

{

floatvp = 0.8f;

floataspect = (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

staticintshaderSize(char*fileName, EShaderType shaderType)

{

//傳回頂點着色器或者片段着色器的大小

charname[100];

strcpy(name, fileName);

switch(shaderType)

{

caseEVertexShader:

strcat(name,".vert");

break;

caseEFragmentShader:

strcat(name,".frag");

break;

default:

printf("ERROR: unknown shader file type\n");

exit(1);

break;

}

intcount = -1;

// Open the file, seek to the end to find its length

intfd = _open(name, _O_RDONLY);

if(fd != -1)

{

count = _lseek(fd, 0, SEEK_END) + 1;

_close(fd);

}

returncount;

}

staticintreadShader(char*fileName, EShaderType shaderType,char*shaderText,intsize)

{

//

// 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;

charname[100];

intcount;

strcpy(name, fileName);

switch(shaderType)

{

caseEVertexShader:

strcat(name,".vert");

break;

caseEFragmentShader:

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);

returncount;

}

intreadShaderSource(char*fileName, GLchar **vertexShader, GLchar **fragmentShader)

{

intvSize, 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);

return0;

}

*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);

return0;

}

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

{

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

return0;

}

return1;

}

intinstallShaders(constGLchar *Vertex,

constGLchar *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)

return0;

// 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)

return0;

// 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);

return1;

}

intmain(intargc,char**argv )

{

intsuccess = 0;

intgl_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();

return0;

}