opengl 2.0 shader简单示例
2014-06-18 14:58
309 查看
本例子选自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,我们也可以将着色器放在程序中存储在一个字符串中。
//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;
}
这里我们只绘制一个简单的三角形,需要为每个顶点指定一个属性值,代表其温度值,着色器中我们对其进行了读取并插值。对于复杂的图形,应当使用顶点数组进行指定。
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();
}
运行效果如下:
整个程序如下:
[align=left]#include <stdlib.h>[/align]
[align=left]#include <stdio.h>[/align]
[align=left]#include <string.h>[/align]
[align=left]#include <fcntl.h>[/align]
[align=left]#include <io.h>[/align]
[align=left]#define GLEW_STATIC 1[/align]
[align=left]#include <GL/glew.h>[/align]
[align=left]#include <GL/glu.h>[/align]
[align=left]#include <GL/glut.h>[/align]
[align=left][/align]
[align=left]//窗口句柄[/align]
[align=left]static GLint window;[/align]
[align=left][/align]
GLuint ProgramObject = 0;
//程序对象
GLuint VertexShaderObject = 0;
//顶点着色器对象
GLuint FragmentShaderObject = 0;
//片段着色器对象
[align=left][/align]
[align=left]//Shader类型[/align]
[align=left]typedef enum {[/align]
[align=left] EVertexShader,[/align]
[align=left] EFragmentShader,[/align]
[align=left]} EShaderType;[/align]
[align=left][/align]
//用来检查OpenGL版本,需要GLSL
2.0支持
void getGlVersion(
int *major,
int *minor )
[align=left]{[/align]
constchar* verstr = (constchar*)glGetString(
GL_VERSION );
if( (verstr == NULL) || (sscanf( verstr,
"%d.%d", major, minor ) != 2) )
[align=left] {[/align]
[align=left] *major = *minor = 0;[/align]
fprintf( stderr,
"Invalid GL_VERSION format!!!/n" );
[align=left] }[/align]
[align=left]}[/align]
[align=left][/align]
[align=left]staticvoid display(void)[/align]
[align=left]{[/align]
[align=left] glLoadIdentity();[/align]
[align=left] glTranslatef(0.0, 0.0, -5.0);[/align]
[align=left] glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);[/align]
[align=left][/align]
[align=left] //查询定点着色器属性变量VertexTemp,并对它进行设置,每个定点需要指定一个属性[/align]
GLint tempLoc = glGetAttribLocationARB(ProgramObject,
"VertexTemp");
[align=left] glBegin(GL_TRIANGLES);[/align]
glVertexAttrib1f(tempLoc, 0.0f);
[align=left] glVertex3f(1.0f,0.0f,0.0f);[/align]
[align=left] glVertexAttrib1f(tempLoc, 0.5f);[/align]
[align=left] glVertex3f(-1.0f,0.0f,0.0f);[/align]
[align=left] glVertexAttrib1f(tempLoc, 1.0f);[/align]
[align=left] glVertex3f(0.0f,1.0f,0.0f);[/align]
[align=left] glEnd();[/align]
[align=left] glFlush();[/align]
[align=left] glutSwapBuffers();[/align]
[align=left]}[/align]
[align=left][/align]
staticvoid reshape(int
wid, int ht)
[align=left]{[/align]
[align=left] float vp = 0.8f;[/align]
float aspect = (float)
wid / (float) ht;
[align=left] [/align]
[align=left] glViewport(0, 0, wid, ht);[/align]
[align=left] glMatrixMode(GL_PROJECTION);[/align]
[align=left] glLoadIdentity();[/align]
[align=left] //glOrtho(-1.0, 1.0, -1.0, 1.0, -10.0, 10.0);[/align]
[align=left] glFrustum(-vp, vp, -vp / aspect, vp / aspect, 3, 10.0);[/align]
[align=left] glMatrixMode(GL_MODELVIEW);[/align]
[align=left] glLoadIdentity();[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][/align]
[align=left]//Shader related functions[/align]
staticint shaderSize(char
*fileName, EShaderType shaderType)
[align=left]{[/align]
[align=left] //返回顶点着色器或者片段着色器的大小[/align]
[align=left] char name[100];[/align]
[align=left] strcpy(name, fileName);[/align]
[align=left][/align]
[align=left] switch (shaderType)[/align]
[align=left] {[/align]
[align=left] case EVertexShader:[/align]
strcat(name,
".vert");
[align=left] break;[/align]
[align=left] case EFragmentShader:[/align]
strcat(name,
".frag");
[align=left] break;[/align]
[align=left] default:[/align]
[align=left] printf("ERROR: unknown shader file type/n");[/align]
[align=left] exit(1);[/align]
[align=left] break;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] int count = -1;[/align]
[align=left] // Open the file, seek to the end to find its length[/align]
[align=left] int fd = _open(name, _O_RDONLY);[/align]
[align=left] if (fd != -1)[/align]
[align=left] {[/align]
[align=left] count = _lseek(fd, 0, SEEK_END) + 1;[/align]
[align=left] _close(fd);[/align]
[align=left] }[/align]
[align=left] return count;[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][/align]
staticint readShader(char
*fileName, EShaderType shaderType, char *shaderText,
int size)
[align=left]{[/align]
[align=left] //[/align]
[align=left] // Reads a shader from the supplied file and returns the shader in the[/align]
[align=left] // arrays passed in. Returns 1 if successful, 0 if an error occurred.[/align]
[align=left] // The parameter size is an upper limit of the amount of bytes to read.[/align]
[align=left] // It is ok for it to be too big.[/align]
[align=left] //[/align]
[align=left] FILE *fh;[/align]
[align=left] char name[100];[/align]
[align=left] int count;[/align]
[align=left][/align]
[align=left] strcpy(name, fileName);[/align]
[align=left][/align]
switch (shaderType)
[align=left] {[/align]
[align=left] case EVertexShader:[/align]
strcat(name,
".vert");
[align=left] break;[/align]
[align=left] case EFragmentShader:[/align]
strcat(name,
".frag");
[align=left] break;[/align]
[align=left] default:[/align]
[align=left] printf("ERROR: unknown shader file type/n");[/align]
[align=left] exit(1);[/align]
[align=left] break;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] // Open the file[/align]
fh = fopen(name,
"r");
[align=left] if (!fh)[/align]
[align=left] return -1;[/align]
[align=left][/align]
[align=left] // Get the shader from a file.[/align]
[align=left] fseek(fh, 0, SEEK_SET);[/align]
[align=left] count = (int) fread(shaderText, 1, size, fh);[/align]
shaderText[count] =
'/0';
[align=left][/align]
[align=left] if (ferror(fh))[/align]
[align=left] count = 0;[/align]
[align=left][/align]
[align=left] fclose(fh);[/align]
[align=left] return count;[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][/align]
[align=left]/*public*/[/align]
int readShaderSource(char *fileName, GLchar **vertexShader,
GLchar **fragmentShader)
[align=left]{[/align]
[align=left] int vSize, fSize;[/align]
[align=left][/align]
[align=left] //[/align]
[align=left] // Allocate memory to hold the source of our shaders.[/align]
[align=left] //[/align]
[align=left] vSize = shaderSize(fileName, EVertexShader);[/align]
[align=left] fSize = shaderSize(fileName, EFragmentShader);[/align]
[align=left][/align]
[align=left] if ((vSize == -1) || (fSize == -1))[/align]
[align=left] {[/align]
[align=left] printf("Cannot determine size of the shader %s/n", fileName);[/align]
[align=left] return 0;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] *vertexShader = (GLchar *) malloc(vSize);[/align]
[align=left] *fragmentShader = (GLchar *) malloc(fSize);[/align]
[align=left][/align]
[align=left] //[/align]
[align=left] // Read the source code[/align]
[align=left] //[/align]
[align=left] if (!readShader(fileName, EVertexShader, *vertexShader, vSize))[/align]
[align=left] {[/align]
[align=left] printf("Cannot read the file %s.vert/n", fileName);[/align]
[align=left] return 0;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] if (!readShader(fileName, EFragmentShader, *fragmentShader, fSize))[/align]
[align=left] {[/align]
[align=left] printf("Cannot read the file %s.frag/n", fileName);[/align]
[align=left] return 0;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] return 1;[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][/align]
[align=left]/*public*/[/align]
[align=left]int installShaders(const GLchar *Vertex,[/align]
const GLchar *Fragment)
[align=left]{[/align]
GLint vertCompiled, fragCompiled;
// status values
[align=left] GLint linked;[/align]
[align=left][/align]
[align=left] // Create a vertex shader object and a fragment shader object[/align]
[align=left][/align]
[align=left] VertexShaderObject = glCreateShader(GL_VERTEX_SHADER);[/align]
[align=left] FragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);[/align]
[align=left][/align]
[align=left] // Load source code strings into shaders[/align]
[align=left][/align]
[align=left] glShaderSource(VertexShaderObject, 1, &Vertex, NULL);[/align]
[align=left] glShaderSource(FragmentShaderObject, 1, &Fragment, NULL);[/align]
[align=left][/align]
[align=left] // Compile the brick vertex shader, and print out[/align]
[align=left] // the compiler log file.[/align]
[align=left][/align]
[align=left] glCompileShader(VertexShaderObject);[/align]
[align=left] glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, &vertCompiled);[/align]
[align=left][/align]
[align=left] // Compile the brick vertex shader, and print out[/align]
[align=left] // the compiler log file.[/align]
[align=left][/align]
[align=left] glCompileShader(FragmentShaderObject);[/align]
[align=left] glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, &fragCompiled);[/align]
[align=left][/align]
[align=left] if (!vertCompiled || !fragCompiled)[/align]
[align=left] return 0;[/align]
[align=left][/align]
[align=left] // Create a program object and attach the two compiled shaders[/align]
[align=left][/align]
[align=left] ProgramObject = glCreateProgram();[/align]
[align=left] glAttachShader(ProgramObject, VertexShaderObject);[/align]
[align=left] glAttachShader(ProgramObject, FragmentShaderObject);[/align]
[align=left][/align]
[align=left] // Link the program object and print out the info log[/align]
[align=left][/align]
[align=left] glLinkProgram(ProgramObject);[/align]
[align=left] glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked);[/align]
[align=left][/align]
[align=left] if (!linked)[/align]
[align=left] return 0;[/align]
[align=left][/align]
[align=left] // Install program object as part of current state[/align]
[align=left][/align]
[align=left] glUseProgram(ProgramObject);[/align]
[align=left][/align]
[align=left] // Set up initial uniform values[/align]
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);
[align=left][/align]
[align=left] return 1;[/align]
[align=left]}[/align]
[align=left][/align]
[align=left]/******************************************************************************/[/align]
[align=left]/*[/align]
[align=left]/* Main[/align]
[align=left]/*[/align]
[align=left]/******************************************************************************/[/align]
int main(
int argc,
char **argv )
[align=left]{[/align]
[align=left] int success = 0;[/align]
[align=left] int gl_major, gl_minor;[/align]
[align=left] GLchar *VertexShaderSource, *FragmentShaderSource;[/align]
[align=left] [/align]
[align=left] glutInit( &argc, argv );[/align]
[align=left] glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);[/align]
[align=left] glutInitWindowSize(500, 500);[/align]
window = glutCreateWindow(
"Temperature Shader");
[align=left] [/align]
[align=left] glutDisplayFunc(display);[/align]
[align=left] glutReshapeFunc(reshape);[/align]
[align=left] [/align]
[align=left] // Initialize the "OpenGL Extension Wrangler" library[/align]
[align=left] glewInit();[/align]
[align=left] [/align]
[align=left] // Make sure that OpenGL 2.0 is supported by the driver[/align]
[align=left] getGlVersion(&gl_major, &gl_minor);[/align]
[align=left] printf("GL_VERSION major=%d minor=%d/n", gl_major, gl_minor);[/align]
[align=left] [/align]
[align=left] if (gl_major < 2)[/align]
[align=left] {[/align]
[align=left] printf("GL_VERSION major=%d minor=%d/n", gl_major, gl_minor);[/align]
[align=left] printf("Support for OpenGL 2.0 is required for this demo...exiting/n");[/align]
[align=left] exit(1);[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] readShaderSource("temp", &VertexShaderSource, &FragmentShaderSource);[/align]
[align=left] success = installShaders(VertexShaderSource, FragmentShaderSource);[/align]
[align=left] [/align]
[align=left] if (success)[/align]
[align=left] glutMainLoop();[/align]
[align=left] [/align]
[align=left] return 0;[/align]
}
//先看顶点着色器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,我们也可以将着色器放在程序中存储在一个字符串中。
//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;
}
这里我们只绘制一个简单的三角形,需要为每个顶点指定一个属性值,代表其温度值,着色器中我们对其进行了读取并插值。对于复杂的图形,应当使用顶点数组进行指定。
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();
}
运行效果如下:
整个程序如下:
[align=left]#include <stdlib.h>[/align]
[align=left]#include <stdio.h>[/align]
[align=left]#include <string.h>[/align]
[align=left]#include <fcntl.h>[/align]
[align=left]#include <io.h>[/align]
[align=left]#define GLEW_STATIC 1[/align]
[align=left]#include <GL/glew.h>[/align]
[align=left]#include <GL/glu.h>[/align]
[align=left]#include <GL/glut.h>[/align]
[align=left][/align]
[align=left]//窗口句柄[/align]
[align=left]static GLint window;[/align]
[align=left][/align]
GLuint ProgramObject = 0;
//程序对象
GLuint VertexShaderObject = 0;
//顶点着色器对象
GLuint FragmentShaderObject = 0;
//片段着色器对象
[align=left][/align]
[align=left]//Shader类型[/align]
[align=left]typedef enum {[/align]
[align=left] EVertexShader,[/align]
[align=left] EFragmentShader,[/align]
[align=left]} EShaderType;[/align]
[align=left][/align]
//用来检查OpenGL版本,需要GLSL
2.0支持
void getGlVersion(
int *major,
int *minor )
[align=left]{[/align]
constchar* verstr = (constchar*)glGetString(
GL_VERSION );
if( (verstr == NULL) || (sscanf( verstr,
"%d.%d", major, minor ) != 2) )
[align=left] {[/align]
[align=left] *major = *minor = 0;[/align]
fprintf( stderr,
"Invalid GL_VERSION format!!!/n" );
[align=left] }[/align]
[align=left]}[/align]
[align=left][/align]
[align=left]staticvoid display(void)[/align]
[align=left]{[/align]
[align=left] glLoadIdentity();[/align]
[align=left] glTranslatef(0.0, 0.0, -5.0);[/align]
[align=left] glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);[/align]
[align=left][/align]
[align=left] //查询定点着色器属性变量VertexTemp,并对它进行设置,每个定点需要指定一个属性[/align]
GLint tempLoc = glGetAttribLocationARB(ProgramObject,
"VertexTemp");
[align=left] glBegin(GL_TRIANGLES);[/align]
glVertexAttrib1f(tempLoc, 0.0f);
[align=left] glVertex3f(1.0f,0.0f,0.0f);[/align]
[align=left] glVertexAttrib1f(tempLoc, 0.5f);[/align]
[align=left] glVertex3f(-1.0f,0.0f,0.0f);[/align]
[align=left] glVertexAttrib1f(tempLoc, 1.0f);[/align]
[align=left] glVertex3f(0.0f,1.0f,0.0f);[/align]
[align=left] glEnd();[/align]
[align=left] glFlush();[/align]
[align=left] glutSwapBuffers();[/align]
[align=left]}[/align]
[align=left][/align]
staticvoid reshape(int
wid, int ht)
[align=left]{[/align]
[align=left] float vp = 0.8f;[/align]
float aspect = (float)
wid / (float) ht;
[align=left] [/align]
[align=left] glViewport(0, 0, wid, ht);[/align]
[align=left] glMatrixMode(GL_PROJECTION);[/align]
[align=left] glLoadIdentity();[/align]
[align=left] //glOrtho(-1.0, 1.0, -1.0, 1.0, -10.0, 10.0);[/align]
[align=left] glFrustum(-vp, vp, -vp / aspect, vp / aspect, 3, 10.0);[/align]
[align=left] glMatrixMode(GL_MODELVIEW);[/align]
[align=left] glLoadIdentity();[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][/align]
[align=left]//Shader related functions[/align]
staticint shaderSize(char
*fileName, EShaderType shaderType)
[align=left]{[/align]
[align=left] //返回顶点着色器或者片段着色器的大小[/align]
[align=left] char name[100];[/align]
[align=left] strcpy(name, fileName);[/align]
[align=left][/align]
[align=left] switch (shaderType)[/align]
[align=left] {[/align]
[align=left] case EVertexShader:[/align]
strcat(name,
".vert");
[align=left] break;[/align]
[align=left] case EFragmentShader:[/align]
strcat(name,
".frag");
[align=left] break;[/align]
[align=left] default:[/align]
[align=left] printf("ERROR: unknown shader file type/n");[/align]
[align=left] exit(1);[/align]
[align=left] break;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] int count = -1;[/align]
[align=left] // Open the file, seek to the end to find its length[/align]
[align=left] int fd = _open(name, _O_RDONLY);[/align]
[align=left] if (fd != -1)[/align]
[align=left] {[/align]
[align=left] count = _lseek(fd, 0, SEEK_END) + 1;[/align]
[align=left] _close(fd);[/align]
[align=left] }[/align]
[align=left] return count;[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][/align]
staticint readShader(char
*fileName, EShaderType shaderType, char *shaderText,
int size)
[align=left]{[/align]
[align=left] //[/align]
[align=left] // Reads a shader from the supplied file and returns the shader in the[/align]
[align=left] // arrays passed in. Returns 1 if successful, 0 if an error occurred.[/align]
[align=left] // The parameter size is an upper limit of the amount of bytes to read.[/align]
[align=left] // It is ok for it to be too big.[/align]
[align=left] //[/align]
[align=left] FILE *fh;[/align]
[align=left] char name[100];[/align]
[align=left] int count;[/align]
[align=left][/align]
[align=left] strcpy(name, fileName);[/align]
[align=left][/align]
switch (shaderType)
[align=left] {[/align]
[align=left] case EVertexShader:[/align]
strcat(name,
".vert");
[align=left] break;[/align]
[align=left] case EFragmentShader:[/align]
strcat(name,
".frag");
[align=left] break;[/align]
[align=left] default:[/align]
[align=left] printf("ERROR: unknown shader file type/n");[/align]
[align=left] exit(1);[/align]
[align=left] break;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] // Open the file[/align]
fh = fopen(name,
"r");
[align=left] if (!fh)[/align]
[align=left] return -1;[/align]
[align=left][/align]
[align=left] // Get the shader from a file.[/align]
[align=left] fseek(fh, 0, SEEK_SET);[/align]
[align=left] count = (int) fread(shaderText, 1, size, fh);[/align]
shaderText[count] =
'/0';
[align=left][/align]
[align=left] if (ferror(fh))[/align]
[align=left] count = 0;[/align]
[align=left][/align]
[align=left] fclose(fh);[/align]
[align=left] return count;[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][/align]
[align=left]/*public*/[/align]
int readShaderSource(char *fileName, GLchar **vertexShader,
GLchar **fragmentShader)
[align=left]{[/align]
[align=left] int vSize, fSize;[/align]
[align=left][/align]
[align=left] //[/align]
[align=left] // Allocate memory to hold the source of our shaders.[/align]
[align=left] //[/align]
[align=left] vSize = shaderSize(fileName, EVertexShader);[/align]
[align=left] fSize = shaderSize(fileName, EFragmentShader);[/align]
[align=left][/align]
[align=left] if ((vSize == -1) || (fSize == -1))[/align]
[align=left] {[/align]
[align=left] printf("Cannot determine size of the shader %s/n", fileName);[/align]
[align=left] return 0;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] *vertexShader = (GLchar *) malloc(vSize);[/align]
[align=left] *fragmentShader = (GLchar *) malloc(fSize);[/align]
[align=left][/align]
[align=left] //[/align]
[align=left] // Read the source code[/align]
[align=left] //[/align]
[align=left] if (!readShader(fileName, EVertexShader, *vertexShader, vSize))[/align]
[align=left] {[/align]
[align=left] printf("Cannot read the file %s.vert/n", fileName);[/align]
[align=left] return 0;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] if (!readShader(fileName, EFragmentShader, *fragmentShader, fSize))[/align]
[align=left] {[/align]
[align=left] printf("Cannot read the file %s.frag/n", fileName);[/align]
[align=left] return 0;[/align]
[align=left] }[/align]
[align=left][/align]
[align=left] return 1;[/align]
[align=left]}[/align]
[align=left][/align]
[align=left][/align]
[align=left]/*public*/[/align]
[align=left]int installShaders(const GLchar *Vertex,[/align]
const GLchar *Fragment)
[align=left]{[/align]
GLint vertCompiled, fragCompiled;
// status values
[align=left] GLint linked;[/align]
[align=left][/align]
[align=left] // Create a vertex shader object and a fragment shader object[/align]
[align=left][/align]
[align=left] VertexShaderObject = glCreateShader(GL_VERTEX_SHADER);[/align]
[align=left] FragmentShaderObject = glCreateShader(GL_FRAGMENT_SHADER);[/align]
[align=left][/align]
[align=left] // Load source code strings into shaders[/align]
[align=left][/align]
[align=left] glShaderSource(VertexShaderObject, 1, &Vertex, NULL);[/align]
[align=left] glShaderSource(FragmentShaderObject, 1, &Fragment, NULL);[/align]
[align=left][/align]
[align=left] // Compile the brick vertex shader, and print out[/align]
[align=left] // the compiler log file.[/align]
[align=left][/align]
[align=left] glCompileShader(VertexShaderObject);[/align]
[align=left] glGetShaderiv(VertexShaderObject, GL_COMPILE_STATUS, &vertCompiled);[/align]
[align=left][/align]
[align=left] // Compile the brick vertex shader, and print out[/align]
[align=left] // the compiler log file.[/align]
[align=left][/align]
[align=left] glCompileShader(FragmentShaderObject);[/align]
[align=left] glGetShaderiv(FragmentShaderObject, GL_COMPILE_STATUS, &fragCompiled);[/align]
[align=left][/align]
[align=left] if (!vertCompiled || !fragCompiled)[/align]
[align=left] return 0;[/align]
[align=left][/align]
[align=left] // Create a program object and attach the two compiled shaders[/align]
[align=left][/align]
[align=left] ProgramObject = glCreateProgram();[/align]
[align=left] glAttachShader(ProgramObject, VertexShaderObject);[/align]
[align=left] glAttachShader(ProgramObject, FragmentShaderObject);[/align]
[align=left][/align]
[align=left] // Link the program object and print out the info log[/align]
[align=left][/align]
[align=left] glLinkProgram(ProgramObject);[/align]
[align=left] glGetProgramiv(ProgramObject, GL_LINK_STATUS, &linked);[/align]
[align=left][/align]
[align=left] if (!linked)[/align]
[align=left] return 0;[/align]
[align=left][/align]
[align=left] // Install program object as part of current state[/align]
[align=left][/align]
[align=left] glUseProgram(ProgramObject);[/align]
[align=left][/align]
[align=left] // Set up initial uniform values[/align]
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);
[align=left][/align]
[align=left] return 1;[/align]
[align=left]}[/align]
[align=left][/align]
[align=left]/******************************************************************************/[/align]
[align=left]/*[/align]
[align=left]/* Main[/align]
[align=left]/*[/align]
[align=left]/******************************************************************************/[/align]
int main(
int argc,
char **argv )
[align=left]{[/align]
[align=left] int success = 0;[/align]
[align=left] int gl_major, gl_minor;[/align]
[align=left] GLchar *VertexShaderSource, *FragmentShaderSource;[/align]
[align=left] [/align]
[align=left] glutInit( &argc, argv );[/align]
[align=left] glutInitDisplayMode( GLUT_RGB | GLUT_DEPTH | GLUT_DOUBLE);[/align]
[align=left] glutInitWindowSize(500, 500);[/align]
window = glutCreateWindow(
"Temperature Shader");
[align=left] [/align]
[align=left] glutDisplayFunc(display);[/align]
[align=left] glutReshapeFunc(reshape);[/align]
[align=left] [/align]
[align=left] // Initialize the "OpenGL Extension Wrangler" library[/align]
[align=left] glewInit();[/align]
[align=left] [/align]
[align=left] // Make sure that OpenGL 2.0 is supported by the driver[/align]
[align=left] getGlVersion(&gl_major, &gl_minor);[/align]
[align=left] printf("GL_VERSION major=%d minor=%d/n", gl_major, gl_minor);[/align]
[align=left] [/align]
[align=left] if (gl_major < 2)[/align]
[align=left] {[/align]
[align=left] printf("GL_VERSION major=%d minor=%d/n", gl_major, gl_minor);[/align]
[align=left] printf("Support for OpenGL 2.0 is required for this demo...exiting/n");[/align]
[align=left] exit(1);[/align]
[align=left] }[/align]
[align=left] [/align]
[align=left] readShaderSource("temp", &VertexShaderSource, &FragmentShaderSource);[/align]
[align=left] success = installShaders(VertexShaderSource, FragmentShaderSource);[/align]
[align=left] [/align]
[align=left] if (success)[/align]
[align=left] glutMainLoop();[/align]
[align=left] [/align]
[align=left] return 0;[/align]
}
相关文章推荐
- 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)
- 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)
- 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)
- 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)
- 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)
- 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)
- 最简单的视音频播放示例6:OpenGL播放YUV420P(通过Texture,使用Shader)
- 利用Spring2.0技术实现RMI的成功简单示例
- Asp.net 2.0 一个简单的联动DropDownList示例(示例代码下载) [zhuan :D]
- (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.2 简单示例(一)
- [导入]Asp.net 2.0 一个简单的联动DropDownList示例(示例代码下载)
- JSF 2.0简单示例
- Asp.net 2.0 一个简单的联动DropDownList示例(示例代码下载)
- 最简单的视音频播放示例5:OpenGL播放RGB/YUV
- 最简单的视音频播放示例5:OpenGL播放RGB/YUV
- 最简单的视音频播放示例5:OpenGL播放RGB/YUV
- Apache MINA 2.0 简单应用示例及与Spring的集成
- BizTalk 2006 简单入门示例程序 Version 2.0(附源项目文件下载)
- opengl简单示例详细说明--建模
- (翻译)《Expert .NET 2.0 IL Assembler》 第一章 简单示例 1.3 类的预先声明