main.cpp:
#include <iostream>
#include"shadertool.h"
#include"glm/glm.hpp"
//using namespace std;
#include"glm/gtc/matrix_transform.hpp"
using glm::mat4;
using glm::vec3;
#define PI 3.1415926
GLuint vaoHandle;
GLuint programHandle;
float angle = 30.0f * PI/180.0f;//转换为弧度制
//we create and populate the vertex buffer objects for each attribute
float positionData[] = {
-0.8f, -0.8f, .0f,
0.8f, -0.8f, 0.0f,
0.0f, 0.8f, 0.0f
};
float colorData[] = {
1.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 1.0f
};
void changeSize(int w,int h)
{
if(h==0)
{
h=1;
}
float ratio=1.0*w/h;
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0,0,w,h);
gluPerspective(45,ratio,1,1000);
glMatrixMode(GL_MODELVIEW);
}
void renderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
angle += 0.01f;
mat4 rotationMatrix = glm::rotate( mat4(1.0f),angle,vec3(0.0f,0.0f,1.0f));
GLuint location = glGetUniformLocation( programHandle, "RotationMatrix");
if(location >= 0)
{
//printf("yes...........\n");
glUniformMatrix4fv( location, 1, GL_FALSE, &rotationMatrix[0][0]);
}
else
{
printf("no...........\n");
}
//in the render func,we bind to the vertex array obj and call glDrawArrays to initiate rendering
glBindVertexArray(vaoHandle);
glDrawArrays(GL_TRIANGLES,0,3);
glutSwapBuffers();
}
void processNormalKeys(unsigned char key,int x,int y)
{
if(key==27)
{
exit(0);
}
}
void setShaders()
{
char* vs_code = LoadShaderFromFile("z_basic.vert");
char* fs_code = LoadShaderFromFile("z_basic.frag");
GLuint v = glCreateShader(GL_VERTEX_SHADER);//create shader obj,返回一个handle
GLuint f = glCreateShader(GL_FRAGMENT_SHADER);
const char* ff = fs_code;
const char* vv = vs_code;
/*
load the source code into shader obj,第三个参数可以是一个字符串数组,可以载入多个文件string
第二个参数是表示string array 的size,one string ,so 1.
最后一个参数表示each source code string is terminated by a null character.
一旦这个函数返回后,表明source code 已经被成功加载在opengl的内部内存,因此,之前的用来存储shader code的字符串变量
可以被释放掉了
*/
glShaderSource(v,1,&vv,NULL);
glShaderSource(f,1,&ff,NULL); //
//free the source code
free(vs_code);
free(fs_code);
//next step:
//compile shader and log error
CompileShader(v,0);
CompileShader(f,1);
//final step : shaders must be linked togehter into a shader program object.
programHandle = glCreateProgram();//create a empty program obj
glAttachShader(programHandle,f);
glAttachShader(programHandle,v);
//link.can use glGetProgramiv to query status(GL_TRUE/GL_FALSE)->glGetProgramiv(GL_LINK_STATUS)
glLinkProgram(programHandle);
//install the program into the opengl pipeline
glUseProgram(programHandle);
//
}
void InitGL(int argc,char* argv[])
{
//
glutInit(&argc,argv); //初始化glut,必须调用,复制黏贴这句话即可
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE ); //设置显示方式,RGB、双缓冲
glutInitWindowPosition(100,100); //位置
glutInitWindowSize(400,400);//窗口大小
glutCreateWindow("GLSL FUN!"); //创建窗口,设置标题
glutDisplayFunc(renderScene); // 当绘制窗口时调用myDisplay
glutIdleFunc(renderScene);
glutReshapeFunc(changeSize);
glutKeyboardFunc(processNormalKeys);
glEnable(GL_DEPTH_TEST);
glClearColor(1.0,1.0,1.0,1.0);//清除颜色设置为白色,这样glclear后面clear color就用白色clear
glewInit();
//
//1.创建
//create and populate the buffer objects
GLuint vboHandles[2];
glGenBuffers(2, vboHandles);
GLuint positionBufferHandle = vboHandles[0];
GLuint colorBufferHandle = vboHandles[1];
//2.
//populate the position buffer
glBindBuffer( GL_ARRAY_BUFFER, positionBufferHandle);
glBufferData( GL_ARRAY_BUFFER, 9 * sizeof(float), positionData, GL_STATIC_DRAW);
//populate color buffer
glBindBuffer( GL_ARRAY_BUFFER, colorBufferHandle);
//最后一个参数告诉我们这个数据是用来干嘛的,static表示不能再被修改
glBufferData( GL_ARRAY_BUFFER, 9 * sizeof(float), colorData, GL_STATIC_DRAW);
//3.create and set up the vertex array objects
glGenVertexArrays(1, &vaoHandle);
glBindVertexArray( vaoHandle );
//enable the vertex attribute arrays
glEnableVertexAttribArray(0);//vertex position
glEnableVertexAttribArray(1);//vertex color
//map index 0 to the position buffer
glBindBuffer( GL_ARRAY_BUFFER, positionBufferHandle);
glVertexAttribPointer(0,3,GL_FLOAT, GL_FALSE, 0 ,NULL);
//map index 1 to the color buffer
glBindBuffer(GL_ARRAY_BUFFER, colorBufferHandle);
glVertexAttribPointer(1,3,GL_FLOAT, GL_FALSE, 0 ,NULL);
}
int main(int argc,char* argv[])
{
//1.
InitGL(argc,argv);
//2.
setShaders();
//3.
// LogGLVersion();
glutMainLoop(); //消息循环
//
//check gl version
return 0;
}
着色器:
z_basic.vert:
#version 430
/*
the main opengl program refers to vertex attributes by associating each input variable with a generic attribute index.
those index are simply integers between 0 and GL_MAX_VERTEX_ATTRIBS - 1.
we can specify the relationship between these indices and the attributes using the layout qualifier.
*/
//input
layout (location=0) in vec3 VertexPosition;
layout (location=1) in vec3 VertexColor;
//output
out vec3 Color;
/*
uniform variables are uintended to used for data that may change relatively infrequently compared to per-vertex attributes.
uniform variables are well suited for the matrics used for modeling , viewing, and projective transformations.
*/
uniform mat4 RotationMatrix;
void main()
{
Color = VertexColor;
gl_Position = RotationMatrix * vec4 ( VertexPosition, 1.0);
}
z_basic.frag:
#version 430
in vec3 Color;
layout (location = 0) out vec4 FragColor;
void main()
{
FragColor = vec4(Color, 1.0);
}
shadertool.cpp:
#include"shadertool.h"
char* LoadShaderFromFile( char* fileName)
{
FILE *fp;
char* content = NULL;
int count= 0;
if( fileName != NULL)
{
fp = fopen(fileName,"rt");
if(fp != NULL)
{
fseek( fp, 0, SEEK_END);
count = ftell(fp);
rewind(fp);
if(count > 0)
{
content = (char*)malloc( sizeof(char)*(count + 1));
count = fread(content,sizeof(char),count,fp);
content[count] = '\0';
}
fclose(fp);
}
}
return content;
}
//compile shader and if error log it.
void CompileShader(GLuint s,int type)
{
glCompileShader(s); //编译shader
//get compile info and log it
GLint result;
//query compile status info by call this func.
glGetShaderiv( s, GL_COMPILE_STATUS, &result);
//if false , query the shader log
if( GL_FALSE == result)
{
if(type == 0 )
fprintf(stderr,"vertex shader compile failed\n");
else fprintf(stderr,"fragment shader compile failed\n");
GLint logLen;
glGetShaderiv( s, GL_INFO_LOG_LENGTH,&logLen);
if( logLen > 0)
{
char* log = new char[ logLen ];
GLsizei written;
glGetShaderInfoLog(s,logLen, &written, log);
fprintf( stderr, "shader log : \n%s",log);
delete[] log;//free the memeory
}
else
{
fprintf( stderr, "log length <= 0");
}
}
}
void LogGLVersion()
{
const GLubyte *renderer = glGetString(GL_RENDERER);
const GLubyte *vendor = glGetString(GL_VENDOR);
const GLubyte *version = glGetString(GL_VERSION);
const GLubyte *glslVersion = glGetString(GL_SHADING_LANGUAGE_VERSION);
GLint major, minor;
glGetIntegerv(GL_MAJOR_VERSION, &major);
glGetIntegerv(GL_MINOR_VERSION, &minor);
printf("GL Vendor :%s\n",vendor);
printf("GL Render :%s\n",renderer);
printf("GL Version string :%s\n",version);
printf("GL Version int :%d.%d\n",major,minor);
printf("GLSL Version :%s\n",glslVersion);
}
效果: