先发个截图:当然看到这个界面大家肯定觉得这不就是个三角形,这不是我想说的,重点在后边。
先附上代码,首先是main.cpp文件:
#include "GL\glew.h"
#include "GL\glut.h"
#include <gl\GL.h>
#include <gl\GLU.h>
#include <Windows.h>
#include <stdio.h>
GLuint program;
GLint attribute_coord2d;
char* file_read(const char* filename)
{
FILE* input = fopen(filename, "rb");
if(input == NULL) return NULL;
if(fseek(input, 0, SEEK_END) == -1) return NULL;
long size = ftell(input);
if(size == -1) return NULL;
if(fseek(input, 0, SEEK_SET) == -1) return NULL;
/*if using c-compiler: dont cast malloc's return value*/
char *content = (char*) malloc( (size_t) size +1 );
if(content == NULL) return NULL;
fread(content, 1, (size_t)size, input);
if(ferror(input)) {
free(content);
return NULL;
}
fclose(input);
content[size] = '\0';
return content;
}
/**
* Display compilation errors from the OpenGL shader compiler
*/
void print_log(GLuint object)
{
GLint log_length = 0;
if (glIsShader(object))
glGetShaderiv(object, GL_INFO_LOG_LENGTH, &log_length);
else if (glIsProgram(object))
glGetProgramiv(object, GL_INFO_LOG_LENGTH, &log_length);
else {
fprintf(stderr, "printlog: Not a shader or a program\n");
return;
}
char* log = (char*)malloc(log_length);
if (glIsShader(object))
glGetShaderInfoLog(object, log_length, NULL, log);
else if (glIsProgram(object))
glGetProgramInfoLog(object, log_length, NULL, log);
fprintf(stderr, "%s", log);
free(log);
}
/**
* Compile the shader from file 'filename', with error handling
*/
GLuint create_shader(const char* filename, GLenum type)
{
const GLchar* source = file_read(filename);
if (source == NULL) {
fprintf(stderr, "Error opening %s: ", filename); perror("");
return 0;
}
GLuint res = glCreateShader(type);
const GLchar* sources[2] = {
#ifdef GL_ES_VERSION_2_0
"#version 100\n"
"#define GLES2\n",
#else
"#version 120\n",
#endif
source };
glShaderSource(res, 2, sources, NULL);
free((void*)source);
glCompileShader(res);
GLint compile_ok = GL_FALSE;
glGetShaderiv(res, GL_COMPILE_STATUS, &compile_ok);
if (compile_ok == GL_FALSE) {
fprintf(stderr, "%s:", filename);
print_log(res);
glDeleteShader(res);
return 0;
}
return res;
}
int init_resources(void)
{
/* FILLED IN LATER */
GLint compile_ok = GL_FALSE, link_ok = GL_FALSE;
GLuint vs, fs;
if ((vs = create_shader("triangle.v.glsl", GL_VERTEX_SHADER)) == 0) return 0;
if ((fs = create_shader("triangle.f.glsl", GL_FRAGMENT_SHADER)) == 0) return 0;
program = glCreateProgram();
glAttachShader(program, vs);
glAttachShader(program, fs);
glLinkProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, &link_ok);
if (!link_ok) {
fprintf(stderr, "glLinkProgram:");
print_log(program);
}
return 0;
}
void onDisplay()
{
/* Clear the background as white */
glClearColor(1.0, 1.0, 1.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(program);
glEnableVertexAttribArray(attribute_coord2d);
GLfloat triangle_vertices[] = {
0.0, 0.8,
-0.8, -0.8,
0.8, -0.8,
};
/* Describe our vertices array to OpenGL (it can't guess its format automatically) */
glVertexAttribPointer(
attribute_coord2d, // attribute
2, // number of elements per vertex, here (x,y)
GL_FLOAT, // the type of each element
GL_FALSE, // take our values as-is
0, // no extra data between each position
triangle_vertices // pointer to the C array
);
/* Push each element in buffer_vertices to the vertex shader */
glDrawArrays(GL_TRIANGLES, 0, 3);
glDisableVertexAttribArray(attribute_coord2d);
/* Display the result */
glutSwapBuffers();
}
void free_resources()
{
glDeleteProgram(program);
}
int main(int argc, char* argv[])
{
/* Glut-related initialising functions */
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_DEPTH);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
glutInitWindowSize(640, 480);
glutCreateWindow("My First Triangle");
/* Extension wrangler initialising */
GLenum glew_status = glewInit();
if (glew_status != GLEW_OK)
{
fprintf(stderr, "Error: %s\n", glewGetErrorString(glew_status));
return EXIT_FAILURE;
}
/* When all init functions runs without errors,
the program can initialise the resources */
if (0 == init_resources())
{
/* We can display it if everything goes OK */
glutDisplayFunc(onDisplay);
glutMainLoop();
}
/* If the program exits in the usual way,
free resources and exit with a success */
free_resources();
return EXIT_SUCCESS;
}
我的操作系统是win7 x64位,采用了glew 和freeglut库,这些库可以从相应的网站上下载,这里就不说了,主要看一个函数create_shader这个函数,里面负责从文件中读取GLSL的代码,然后将其编译,后面将其连接然后进行执行。将三个文件放在同一目录下即可编译通过,那些繁琐的理论知识这里就不废话了。
接下来来看这两个文件吧(triangle.v.glsl和triangle.f.glsl):
//triangle.v.glsl
attribute vec2 coord2d;
void main(void)
{
gl_Position = vec4(coord2d, 0.0, 1.0);
}
//triangle.f.glsl
void main(void)
{
gl_FragColor[0] = gl_FragCoord.x/640.0;
gl_FragColor[1] = gl_FragCoord.y/480.0;
gl_FragColor[2] = 0.5;
gl_FragColor[3] = floor(mod(gl_FragCoord.y, 2.0));
};