OpenGL learning entry use record

OpenGL learning path 1 - open a window

New main.cpp

#include<gl/freeglut.h>

void render()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glutSwapBuffers();
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");
	/*
		窗口的背景颜色
	*/
	glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
	glutDisplayFunc(render);
	glutMainLoop();
}

OpenGL Learning Road 2----Draw a point

Create a new opengl_math.h content as follows

#ifndef __OPENGL_MATH_H
#define __OPENGL_MATH_H

//向量
typedef float Vector3f[3];

void LoadVector3(Vector3f v, const float x, const float y, const float z)
{
	v[0] = x, v[1] = y, v[2] = z;
}


#endif

The content of main.cpp is as follows

#include<stdio.h>
#define GLEW_STATIC
#include<gl/glew.h>
#include<gl/freeglut.h>
#include<GL/freeglut.h>
#include "opengl_math.h"


GLuint VBO, IBO;


void CreateVertexBuffer()
{
	//创建一个有顶点的顶点数组
	Vector3f Vertices[1];
	LoadVector3(Vertices[0], 0.0f, 0.0f, 0.0f);
	//创建缓冲器
	glGenBuffers(1, &VBO);
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//绑定顶点数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

}

void render()
{
	glClear(GL_COLOR_BUFFER_BIT);

	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	
	/*
		告诉管线怎样解析bufer的数据
		第一个参数是属性的索引,这里只有一组数据默认为0,如果开始使用shader着色器时,我们既要明确的设置着色器中的属性索引同时也要检索它
		第二个参数指属性中元素的个数,这里是3个,我们长度为3的浮点数数组,同时也代表XYZ的坐标
		第三个参数指元素的数据类型,这里时FLOAT
		第四个参数指明我们是否想让我们的属性在被管线使用之前被单位化,这里数据不变所以设为0
		第五个参数是偏移距离,我们通常不止存储位置信息,假如我们存储的数据是一组(X,Y,Z,R,G,B),而这一组RGB的偏移位置就是X+Y+Z的大小(以后用到的时候会理解的)

	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

	//开始绘制一个点
	glDrawArrays(GL_POINTS, 0, 1);
	
	glutSwapBuffers();
}

int main(int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");

	
	//检查glew是否就绪,必须要在GLUT初始化之后
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error:'%s'\n", glewGetErrorString(res));
		return 0;
	}
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	//创建顶点缓冲器
	CreateVertexBuffer();
	//开始绘制
	glutDisplayFunc(render);

	glutMainLoop();
	return 0;
}

When drawing 3 points, glEnableVertexAttribArray(0) function is required

#include<stdio.h>
#define GLEW_STATIC
#include<gl/glew.h>
#include<gl/freeglut.h>
#include<GL/freeglut.h>
#include "opengl_math.h"


GLuint VBO, IBO;


void CreateVertexBuffer()
{
	//创建一个有顶点的顶点数组
	Vector3f Vertices[3];
	LoadVector3(Vertices[0], -0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[1], 0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[2], 0.0f, 0.5f, 0.0f);
	//创建缓冲器
	glGenBuffers(1, &VBO);
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//绑定顶点数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

}

void render()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glEnableVertexAttribArray(0);

	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	
	/*
		告诉管线怎样解析bufer的数据
		第一个参数是属性的索引,这里只有一组数据默认为0,如果开始使用shader着色器时,我们既要明确的设置着色器中的属性索引同时也要检索它
		第二个参数指属性中元素的个数,这里是3个,我们长度为3的浮点数数组,同时也代表XYZ的坐标
		第三个参数指元素的数据类型,这里时FLOAT
		第四个参数指明我们是否想让我们的属性在被管线使用之前被单位化,这里数据不变所以设为0
		第五个参数是步长,我们通常不止存储位置信息,假如我们存储的数据是一组(X,Y,Z,R,G,B),而这一组RGB的偏移位置就是X+Y+Z的大小(以后用到的时候会理解的)

	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	/*glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);*/
	//glPointSize(3);
	//开始绘制3个点
	glDrawArrays(GL_POINTS, 0, 3);

	glutSwapBuffers();
}

int main(int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");

	
	//检查glew是否就绪,必须要在GLUT初始化之后
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error:'%s'\n", glewGetErrorString(res));
		return 0;
	}
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	//创建顶点缓冲器
	CreateVertexBuffer();
	//开始绘制
	glutDisplayFunc(render);

	glutMainLoop();
	return 0;
}

OpenGL Learning Road 3----Draw a triangle

#include<stdio.h>
#define GLEW_STATIC
#include<gl/glew.h>
#include<gl/freeglut.h>
#include<GL/freeglut.h>
#include "opengl_math.h"


GLuint VBO, IBO;


void CreateVertexBuffer()
{
	//创建一个有顶点的顶点数组
	Vector3f Vertices[3];
	LoadVector3(Vertices[0], -0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[1], 0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[2], 0.0f, 0.5f, 0.0f);
	//创建缓冲器
	glGenBuffers(1, &VBO);
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//绑定顶点数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

}

void render()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glEnableVertexAttribArray(0);

	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	
	/*
		告诉管线怎样解析bufer的数据
		第一个参数是属性的索引,这里只有一组数据默认为0,如果开始使用shader着色器时,我们既要明确的设置着色器中的属性索引同时也要检索它
		第二个参数指属性中元素的个数,这里是3个,我们长度为3的浮点数数组,同时也代表XYZ的坐标
		第三个参数指元素的数据类型,这里时FLOAT
		第四个参数指明我们是否想让我们的属性在被管线使用之前被单位化,这里数据不变所以设为0
		第五个参数是步长,我们通常不止存储位置信息,假如我们存储的数据是一组(X,Y,Z,R,G,B),而这一组RGB的偏移位置就是X+Y+Z的大小(以后用到的时候会理解的)

	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	/*glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);*/
	//glPointSize(3);
	//开始绘制3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);

	glutSwapBuffers();
}

int main(int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");

	
	//检查glew是否就绪,必须要在GLUT初始化之后
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error:'%s'\n", glewGetErrorString(res));
		return 0;
	}
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	//创建顶点缓冲器
	CreateVertexBuffer();
	//开始绘制
	glutDisplayFunc(render);

	glutMainLoop();
	return 0;
}

Drawing a colored triangle requires glColor3f function, solid color fill

#include<stdio.h>
#define GLEW_STATIC
#include<gl/glew.h>
#include<gl/freeglut.h>
#include<GL/freeglut.h>
#include "opengl_math.h"


GLuint VBO, IBO;


void CreateVertexBuffer()
{
	//创建一个有顶点的顶点数组
	Vector3f Vertices[3];
	LoadVector3(Vertices[0], -0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[1], 0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[2], 0.0f, 0.5f, 0.0f);
	//创建缓冲器
	glGenBuffers(1, &VBO);
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//绑定顶点数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

}

void render()
{
	glClear(GL_COLOR_BUFFER_BIT);
	glEnableVertexAttribArray(0);
	
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	
	/*
		告诉管线怎样解析bufer的数据
		第一个参数是属性的索引,这里只有一组数据默认为0,如果开始使用shader着色器时,我们既要明确的设置着色器中的属性索引同时也要检索它
		第二个参数指属性中元素的个数,这里是3个,我们长度为3的浮点数数组,同时也代表XYZ的坐标
		第三个参数指元素的数据类型,这里时FLOAT
		第四个参数指明我们是否想让我们的属性在被管线使用之前被单位化,这里数据不变所以设为0
		第五个参数是步长,我们通常不止存储位置信息,假如我们存储的数据是一组(X,Y,Z,R,G,B),而这一组RGB的偏移位置就是X+Y+Z的大小(以后用到的时候会理解的)

	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	/*glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);*/
	//glPointSize(3);
	//开始绘制3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);

	glutSwapBuffers();
}

int main(int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");

	
	//检查glew是否就绪,必须要在GLUT初始化之后
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error:'%s'\n", glewGetErrorString(res));
		return 0;
	}
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	//创建顶点缓冲器
	CreateVertexBuffer();
	//开始绘制
	glutDisplayFunc(render);

	glutMainLoop();
	return 0;
}

OpenGL Learning Road 4----Using shaders (shader)

The vertex shader determines where to draw the shape, and the fragment shader determines the color to draw the shape

New shader.vs vertex shader

#version 330

layout (location = 0) in vec3 Position;

void main()
{

	//gl_Position是内置变量,作为输出变量,用来保存顶点位置的齐次坐标,即就是顶点着色器输出的顶点位置信息存储的地方

	gl_Position = vec4(0.5 * Position.x, 0.5 * Position .y, Position.z, 1.0);
}

Create a new shader.fs fragment shader

#version 330

out vec4 FragColor;
void main()
{
	FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}

The main.cpp in this section has written a lot. Compile the shader written in GLSL and run it

#include<stdio.h>
#include<string>
#define GLEW_STATIC
#include<gl/glew.h>
#include<gl/freeglut.h>
#include<GL/freeglut.h>
#include "opengl_math.h"
#include <fstream>
using namespace std;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";

GLuint VBO, IBO;


static void render()
{
	glClear(GL_COLOR_BUFFER_BIT);
	
	/*
		glEnableVertexAttribArray 渲染回调函数 与glDisableVertexAttribArray对应使用
		开启一个顶点的属性,这里参数为0,即开启索引为0的顶点属性,在渲染管线中的顶点着色器“layout (location = 0) in vec3 Position”
		相对应,只有开启了索引为0的顶点属性,顶点着色色器才能过去缓存区索引为0的数据。
	*/
	glEnableVertexAttribArray(0);

	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	/*
		告诉管线怎样解析bufer的数据
		第一个参数是属性的索引,这里只有一组数据默认为0,如果开始使用shader着色器时,我们既要明确的设置着色器中的属性索引同时也要检索它
		第二个参数指属性中元素的个数,这里是3个,我们长度为3的浮点数数组,同时也代表XYZ的坐标
		第三个参数指元素的数据类型,这里时FLOAT
		第四个参数指明我们是否想让我们的属性在被管线使用之前被单位化,这里数据不变所以设为0
		第五个参数是步长,我们通常不止存储位置信息,假如我们存储的数据是一组(X,Y,Z,R,G,B),而这一组RGB的偏移位置就是X+Y+Z的大小(以后用到的时候会理解的)

	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	/*glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);*/
	//glPointSize(3);
	//开始绘制3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glDisableVertexAttribArray(0);

	glutSwapBuffers();
}

static void InitializeGlutCallbacks()
{
	//开始绘制
	glutDisplayFunc(render);
}

static void CreateVertexBuffer()
{
	//创建一个有顶点的顶点数组
	Vector3f Vertices[3];
	LoadVector3(Vertices[0], -0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[1], 0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[2], 0.0f, 0.5f, 0.0f);
	//创建缓冲器
	glGenBuffers(1, &VBO);
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//绑定顶点数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

}

/*
	函数名:ReadFile
	读取GLSL源代码
*/
bool ReadFile(const char *pFileName, string &outfile)
{
	ifstream f(pFileName);
	bool ret = false;
	if (f.is_open()) {
		string line;
		while (getline(f, line)) {
			outfile.append(line);
			outfile.append("\n");
		}
		f.close();
		ret = true;
	}
	else {
		fprintf(stderr, "%s:%d unable to open dile '%s'\n", __FILE__, __LINE__, pFileName);
	}
	return ret;
}

static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{

	/*
		创建一个着色器对象
	*/
	GLuint ShaderObj = glCreateShader(ShaderType);
	if (ShaderObj == 0) {
		fprintf(stderr, "Error creating shader type %d\n", ShaderType);
		exit(0);
	}
	/*
		将着色器源代码编译为对象
		glShaderSource函数:
			第一个参数是着色器对象
			第二个参数是两个数组的元素个数,这里只有一个
			第三个参数是源代码数据(实际是一个长度为count的数组,数组里每个元素都是一个字符串)
			第四个参数是对应源代码的长度(实际上就是长度count的数组里面每个元素字符串的长度)
			这里为了简化操作就用了一个字符串保存所有的shader源代码,用一个整形数组保存了源代码长度

	*/
	const GLchar *p[1];
	p[0] = pShaderText;
	GLint Lengths[1];
	Lengths[0] = strlen(pShaderText);
	glShaderSource(ShaderObj, 1, p, Lengths);
	//编译
	glCompileShader(ShaderObj);
	/*
		验证着色器编译是否成功
	*/
	//check the error about shader

	GLint success;
	glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
	if (!success) {
		GLchar InfoLog[1024];
		glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
		fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
		exit(1);
	}
	//bound the shader object to shader program
	glAttachShader(ShaderProgram, ShaderObj);
}

void CompilerShaders()
{
	/*
		创建一个着色器程序
	*/
	GLuint ShaderProgram = glCreateProgram();
	if (ShaderProgram == 0) {
		fprintf(stderr, "Error: Creating shader Program\n");
		exit(0);
	}
	string vs, fs;
	if (!ReadFile(pVSFileName, vs)){
		exit(0);
	}
	if (!ReadFile(pFSFileName, fs)){
		exit(0);
	}
	//多个着色器对象链接为一个着色器程序
	AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
	AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);

	GLint Success = 0;
	GLchar ErrorLog[1024] = { 0 };
	glLinkProgram(ShaderProgram);

	//检查是否连接成功
	glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
	if (Success == 0) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	//check if it can be execute
	glValidateProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
		exit(1);
	}
	//使用程序
	glUseProgram(ShaderProgram);
}



int main(int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");

	
	//检查glew是否就绪,必须要在GLUT初始化之后
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error:'%s'\n", glewGetErrorString(res));
		return 0;
	}
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	//创建顶点缓冲器
	CreateVertexBuffer();
	
	CompilerShaders();

	InitializeGlutCallbacks();

	glutMainLoop();

	return 0;
}

OpenGL Learning Road 5----Use Uniform Variables (Uniform Variables)

#include<stdio.h>
#include<string>
#define GLEW_STATIC
#include<gl/glew.h>
#include<gl/freeglut.h>
#include<GL/freeglut.h>
#include<assert.h>
#include "opengl_math.h"
#include <fstream>
using namespace std;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";

GLuint VBO, IBO;
GLint gScaleLocation; //位置中间变量


static void Render()
{
	glClear(GL_COLOR_BUFFER_BIT);


	static float Scale = 0.0f;
	Scale += 0.01f;//相当于x轴不断变大
	//将值传递给shader
	glUniform1f(gScaleLocation, sinf(Scale));

	
	/*
		glEnableVertexAttribArray 渲染回调函数 与glDisableVertexAttribArray对应使用
		开启一个顶点的属性,这里参数为0,即开启索引为0的顶点属性,在渲染管线中的顶点着色器“layout (location = 0) in vec3 Position”
		相对应,只有开启了索引为0的顶点属性,顶点着色色器才能过去缓存区索引为0的数据。
	*/
	glEnableVertexAttribArray(0);

	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	/*
		告诉管线怎样解析bufer的数据
		第一个参数是属性的索引,这里只有一组数据默认为0,如果开始使用shader着色器时,我们既要明确的设置着色器中的属性索引同时也要检索它
		第二个参数指属性中元素的个数,这里是3个,我们长度为3的浮点数数组,同时也代表XYZ的坐标
		第三个参数指元素的数据类型,这里时FLOAT
		第四个参数指明我们是否想让我们的属性在被管线使用之前被单位化,这里数据不变所以设为0
		第五个参数是步长,我们通常不止存储位置信息,假如我们存储的数据是一组(X,Y,Z,R,G,B),而这一组RGB的偏移位置就是X+Y+Z的大小(以后用到的时候会理解的)

	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	/*glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);*/
	//glPointSize(3);
	//开始绘制3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glDisableVertexAttribArray(0);

	glutSwapBuffers();
}

static void InitializeGlutCallbacks()
{
	//开始绘制
	glutDisplayFunc(Render);
	//将渲染回调注册为全局闲置回调
	glutIdleFunc(Render);
}

static void CreateVertexBuffer()
{
	//创建一个有顶点的顶点数组
	Vector3f Vertices[3];
	LoadVector3(Vertices[0], -0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[1], 0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[2], 0.0f, 0.5f, 0.0f);
	//创建缓冲器
	glGenBuffers(1, &VBO);
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//绑定顶点数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

}

/*
	函数名:ReadFile
	读取GLSL源代码
*/
bool ReadFile(const char *pFileName, string &outfile)
{
	ifstream f(pFileName);
	bool ret = false;
	if (f.is_open()) {
		string line;
		while (getline(f, line)) {
			outfile.append(line);
			outfile.append("\n");
		}
		f.close();
		ret = true;
	}
	else {
		fprintf(stderr, "%s:%d unable to open dile '%s'\n", __FILE__, __LINE__, pFileName);
	}
	return ret;
}

static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{

	/*
		创建一个着色器对象
	*/
	GLuint ShaderObj = glCreateShader(ShaderType);
	if (ShaderObj == 0) {
		fprintf(stderr, "Error creating shader type %d\n", ShaderType);
		exit(0);
	}
	/*
		将着色器源代码编译为对象
		glShaderSource函数:
			第一个参数是着色器对象
			第二个参数是两个数组的元素个数,这里只有一个
			第三个参数是源代码数据(实际是一个长度为count的数组,数组里每个元素都是一个字符串)
			第四个参数是对应源代码的长度(实际上就是长度count的数组里面每个元素字符串的长度)
			这里为了简化操作就用了一个字符串保存所有的shader源代码,用一个整形数组保存了源代码长度

	*/
	const GLchar *p[1];
	p[0] = pShaderText;
	GLint Lengths[1];
	Lengths[0] = strlen(pShaderText);
	glShaderSource(ShaderObj, 1, p, Lengths);
	//编译
	glCompileShader(ShaderObj);
	/*
		验证着色器编译是否成功
	*/
	//check the error about shader

	GLint success;
	glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
	if (!success) {
		GLchar InfoLog[1024];
		glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
		fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
		exit(1);
	}
	//bound the shader object to shader program
	glAttachShader(ShaderProgram, ShaderObj);
}

void CompilerShaders()
{
	/*
		创建一个着色器程序
	*/
	GLuint ShaderProgram = glCreateProgram();
	if (ShaderProgram == 0) {
		fprintf(stderr, "Error: Creating shader Program\n");
		exit(0);
	}
	string vs, fs;
	if (!ReadFile(pVSFileName, vs)){
		exit(0);
	}
	if (!ReadFile(pFSFileName, fs)){
		exit(0);
	}
	//多个着色器对象链接为一个着色器程序
	AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
	AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);

	GLint Success = 0;
	GLchar ErrorLog[1024] = { 0 };
	glLinkProgram(ShaderProgram);

	//检查是否连接成功
	glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
	if (Success == 0) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	//check if it can be execute
	glValidateProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
		exit(1);
	}
	//使用程序
	glUseProgram(ShaderProgram);


	//查询获取一致变量的位置
	gScaleLocation = glGetUniformLocation(ShaderProgram, "gScale");
	//检查错误
	assert(gScaleLocation != 0xFFFFFFFF);

}



int main(int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");

	
	//检查glew是否就绪,必须要在GLUT初始化之后
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error:'%s'\n", glewGetErrorString(res));
		return 0;
	}
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	//创建顶点缓冲器
	CreateVertexBuffer();
	
	CompilerShaders();

	InitializeGlutCallbacks();

	glutMainLoop();

	return 0;
}
#include<stdio.h>
#include<string>
#define GLEW_STATIC
#include<gl/glew.h>
#include<gl/freeglut.h>
#include<GL/freeglut.h>
#include<assert.h>
#include "opengl_math.h"
#include <fstream>
using namespace std;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";

GLuint VBO, IBO;
GLint gScaleLocation; //位置中间变量


static void Render()
{
	glClear(GL_COLOR_BUFFER_BIT);


	static float Scale = 0.0f;
	Scale += 0.001f;

	Matrix44f World;
	ScaleMatrix44(World, sinf(Scale), sinf(Scale), sinf(Scale));
	glUniformMatrix4fv(gScaleLocation, 1, GL_FALSE, &World[0]);

	
	/*
		glEnableVertexAttribArray 渲染回调函数 与glDisableVertexAttribArray对应使用
		开启一个顶点的属性,这里参数为0,即开启索引为0的顶点属性,在渲染管线中的顶点着色器“layout (location = 0) in vec3 Position”
		相对应,只有开启了索引为0的顶点属性,顶点着色色器才能过去缓存区索引为0的数据。
	*/
	glEnableVertexAttribArray(0);

	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	/*
		告诉管线怎样解析bufer的数据
		第一个参数是属性的索引,这里只有一组数据默认为0,如果开始使用shader着色器时,我们既要明确的设置着色器中的属性索引同时也要检索它
		第二个参数指属性中元素的个数,这里是3个,我们长度为3的浮点数数组,同时也代表XYZ的坐标
		第三个参数指元素的数据类型,这里时FLOAT
		第四个参数指明我们是否想让我们的属性在被管线使用之前被单位化,这里数据不变所以设为0
		第五个参数是步长,我们通常不止存储位置信息,假如我们存储的数据是一组(X,Y,Z,R,G,B),而这一组RGB的偏移位置就是X+Y+Z的大小(以后用到的时候会理解的)

	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	/*glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);*/
	//glPointSize(3);
	//开始绘制3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glDisableVertexAttribArray(0);

	glutSwapBuffers();
}

static void InitializeGlutCallbacks()
{
	//开始绘制
	glutDisplayFunc(Render);
	//将渲染回调注册为全局闲置回调
	glutIdleFunc(Render);
}

static void CreateVertexBuffer()
{
	//创建一个有顶点的顶点数组
	Vector3f Vertices[3];
	LoadVector3(Vertices[0], -0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[1], 0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[2], 0.0f, 0.5f, 0.0f);
	//创建缓冲器
	glGenBuffers(1, &VBO);
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//绑定顶点数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

}

/*
	函数名:ReadFile
	读取GLSL源代码
*/
bool ReadFile(const char *pFileName, string &outfile)
{
	ifstream f(pFileName);
	bool ret = false;
	if (f.is_open()) {
		string line;
		while (getline(f, line)) {
			outfile.append(line);
			outfile.append("\n");
		}
		f.close();
		ret = true;
	}
	else {
		fprintf(stderr, "%s:%d unable to open dile '%s'\n", __FILE__, __LINE__, pFileName);
	}
	return ret;
}

static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{

	/*
		创建一个着色器对象
	*/
	GLuint ShaderObj = glCreateShader(ShaderType);
	if (ShaderObj == 0) {
		fprintf(stderr, "Error creating shader type %d\n", ShaderType);
		exit(0);
	}
	/*
		将着色器源代码编译为对象
		glShaderSource函数:
			第一个参数是着色器对象
			第二个参数是两个数组的元素个数,这里只有一个
			第三个参数是源代码数据(实际是一个长度为count的数组,数组里每个元素都是一个字符串)
			第四个参数是对应源代码的长度(实际上就是长度count的数组里面每个元素字符串的长度)
			这里为了简化操作就用了一个字符串保存所有的shader源代码,用一个整形数组保存了源代码长度

	*/
	const GLchar *p[1];
	p[0] = pShaderText;
	GLint Lengths[1];
	Lengths[0] = strlen(pShaderText);
	glShaderSource(ShaderObj, 1, p, Lengths);
	//编译
	glCompileShader(ShaderObj);
	/*
		验证着色器编译是否成功
	*/
	//check the error about shader

	GLint success;
	glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
	if (!success) {
		GLchar InfoLog[1024];
		glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
		fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
		exit(1);
	}
	//bound the shader object to shader program
	glAttachShader(ShaderProgram, ShaderObj);
}

void CompilerShaders()
{
	/*
		创建一个着色器程序
	*/
	GLuint ShaderProgram = glCreateProgram();
	if (ShaderProgram == 0) {
		fprintf(stderr, "Error: Creating shader Program\n");
		exit(0);
	}
	string vs, fs;
	if (!ReadFile(pVSFileName, vs)){
		exit(0);
	}
	if (!ReadFile(pFSFileName, fs)){
		exit(0);
	}
	//多个着色器对象链接为一个着色器程序
	AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
	AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);

	GLint Success = 0;
	GLchar ErrorLog[1024] = { 0 };
	glLinkProgram(ShaderProgram);

	//检查是否连接成功
	glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
	if (Success == 0) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	//check if it can be execute
	glValidateProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
		exit(1);
	}
	//使用程序
	glUseProgram(ShaderProgram);


	//查询获取一致变量的位置
	gScaleLocation = glGetUniformLocation(ShaderProgram, "gWorld");
	//检查错误
	assert(gScaleLocation != 0xFFFFFFFF);

}



int main(int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");

	
	//检查glew是否就绪,必须要在GLUT初始化之后
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error:'%s'\n", glewGetErrorString(res));
		return 0;
	}
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	//创建顶点缓冲器
	CreateVertexBuffer();
	
	CompilerShaders();

	InitializeGlutCallbacks();

	glutMainLoop();

	return 0;
}

OpenGL Learning Road 7--Interpolation

a triangle with multiple colors

#include<stdio.h>
#include<string>
#define GLEW_STATIC
#include<gl/glew.h>
#include<gl/freeglut.h>
#include<GL/freeglut.h>
#include<assert.h>
#include "opengl_math.h"
#include <fstream>
using namespace std;
const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";

GLuint VBO, IBO;
GLint gWorldLocation; //位置中间变量


static void Render()
{
	glClear(GL_COLOR_BUFFER_BIT);


	static float Scale = 0.0f;
	Scale += 0.001f;

	Matrix44f World;
	ScaleMatrix44(World, sinf(Scale), sinf(Scale), sinf(Scale));
	glUniformMatrix4fv(gWorldLocation, 1, GL_FALSE, &World[0]);

	
	/*
		glEnableVertexAttribArray 渲染回调函数 与glDisableVertexAttribArray对应使用
		开启一个顶点的属性,这里参数为0,即开启索引为0的顶点属性,在渲染管线中的顶点着色器“layout (location = 0) in vec3 Position”
		相对应,只有开启了索引为0的顶点属性,顶点着色色器才能过去缓存区索引为0的数据。
	*/
	glEnableVertexAttribArray(0);

	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);

	/*
		告诉管线怎样解析bufer的数据
		第一个参数是属性的索引,这里只有一组数据默认为0,如果开始使用shader着色器时,我们既要明确的设置着色器中的属性索引同时也要检索它
		第二个参数指属性中元素的个数,这里是3个,我们长度为3的浮点数数组,同时也代表XYZ的坐标
		第三个参数指元素的数据类型,这里时FLOAT
		第四个参数指明我们是否想让我们的属性在被管线使用之前被单位化,这里数据不变所以设为0
		第五个参数是步长,我们通常不止存储位置信息,假如我们存储的数据是一组(X,Y,Z,R,G,B),而这一组RGB的偏移位置就是X+Y+Z的大小(以后用到的时候会理解的)

	*/
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	/*glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 0, 0);*/
	//glPointSize(3);
	//开始绘制3个点
	glDrawArrays(GL_TRIANGLES, 0, 3);
	glDisableVertexAttribArray(0);

	glutSwapBuffers();
}

static void InitializeGlutCallbacks()
{
	//开始绘制
	glutDisplayFunc(Render);
	//将渲染回调注册为全局闲置回调
	glutIdleFunc(Render);
}

static void CreateVertexBuffer()
{
	//创建一个有顶点的顶点数组
	Vector3f Vertices[3];
	LoadVector3(Vertices[0], -0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[1], 0.5f, -0.5f, 0.0f);
	LoadVector3(Vertices[2], 0.0f, 0.5f, 0.0f);
	//创建缓冲器
	glGenBuffers(1, &VBO);
	//绑定GL_ARRAY_BUFFER缓冲器
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	//绑定顶点数据
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

}

/*
	函数名:ReadFile
	读取GLSL源代码
*/
bool ReadFile(const char *pFileName, string &outfile)
{
	ifstream f(pFileName);
	bool ret = false;
	if (f.is_open()) {
		string line;
		while (getline(f, line)) {
			outfile.append(line);
			outfile.append("\n");
		}
		f.close();
		ret = true;
	}
	else {
		fprintf(stderr, "%s:%d unable to open dile '%s'\n", __FILE__, __LINE__, pFileName);
	}
	return ret;
}

static void AddShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{

	/*
		创建一个着色器对象
	*/
	GLuint ShaderObj = glCreateShader(ShaderType);
	if (ShaderObj == 0) {
		fprintf(stderr, "Error creating shader type %d\n", ShaderType);
		exit(0);
	}
	/*
		将着色器源代码编译为对象
		glShaderSource函数:
			第一个参数是着色器对象
			第二个参数是两个数组的元素个数,这里只有一个
			第三个参数是源代码数据(实际是一个长度为count的数组,数组里每个元素都是一个字符串)
			第四个参数是对应源代码的长度(实际上就是长度count的数组里面每个元素字符串的长度)
			这里为了简化操作就用了一个字符串保存所有的shader源代码,用一个整形数组保存了源代码长度

	*/
	const GLchar *p[1];
	p[0] = pShaderText;
	GLint Lengths[1];
	Lengths[0] = strlen(pShaderText);
	glShaderSource(ShaderObj, 1, p, Lengths);
	//编译
	glCompileShader(ShaderObj);
	/*
		验证着色器编译是否成功
	*/
	//check the error about shader

	GLint success;
	glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
	if (!success) {
		GLchar InfoLog[1024];
		glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
		fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
		exit(1);
	}
	//bound the shader object to shader program
	glAttachShader(ShaderProgram, ShaderObj);
}

static void CompilerShaders()
{
	/*
		创建一个着色器程序
	*/
	GLuint ShaderProgram = glCreateProgram();
	if (ShaderProgram == 0) {
		fprintf(stderr, "Error: Creating shader Program\n");
		exit(0);
	}
	string vs, fs;
	if (!ReadFile(pVSFileName, vs)){
		exit(0);
	}
	if (!ReadFile(pFSFileName, fs)){
		exit(0);
	}
	//多个着色器对象链接为一个着色器程序
	AddShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
	AddShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);

	GLint Success = 0;
	GLchar ErrorLog[1024] = { 0 };
	glLinkProgram(ShaderProgram);

	//检查是否连接成功
	glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
	if (Success == 0) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	//check if it can be execute
	glValidateProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
		exit(1);
	}
	//使用程序
	glUseProgram(ShaderProgram);


	//查询获取一致变量的位置
	gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld");
	//检查错误
	assert(gWorldLocation != 0xFFFFFFFF);

}



int main(int argc, char **argv)
{

	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowSize(1024, 768);
	glutInitWindowPosition(10, 10);
	glutCreateWindow("Create Window!");

	
	//检查glew是否就绪,必须要在GLUT初始化之后
	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error:'%s'\n", glewGetErrorString(res));
		return 0;
	}
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	//创建顶点缓冲器
	CreateVertexBuffer();
	
	CompilerShaders();

	InitializeGlutCallbacks();

	glutMainLoop();

	return 0;
}

OpenGL Learning Road 8----Index Drawing

#include <stdio.h>
#include <string>
#include<math.h>
#define GLEW_STATIC
#include <gl/glew.h>
#include <gl/freeglut.h>
#include<fstream>
#include<assert.h>
#include "opengl_math.h"

using namespace std;

GLuint VBO, IBO;
GLuint gWorldLocation;

const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";

bool ReadFile(const char* FileName, string &outFile)
{
	ifstream f(FileName);
	bool ret = false;

	if (f.is_open()) {
		string line;
		while (getline(f, line)) {
			outFile.append(line);
			outFile.append("\n");
		}
		f.close();
		ret = true;
	}
	else {
		fprintf(stderr, "%s:%d: unable to open file '%s'\n", __FILE__, __LINE__, FileName);
		system("pause");
	}
	return ret;
}

static void Render()
{
	glClear(GL_COLOR_BUFFER_BIT);

	static float Scale = 0.0f;
	Scale += 0.001f;

	Matrix44f World;

	RotationMatrix44(World, Scale, 0, 1, 0);

	glUniformMatrix4fv(gWorldLocation, 1, GL_FALSE, &World[0]);

	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

	//绘制前绑定索引缓冲
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
	//索引绘制图形
	glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);

	glDisableVertexAttribArray(0);
	glutSwapBuffers();

}

static void InitializeGlutCallbacks()
{
	glutDisplayFunc(Render);
	glutIdleFunc(Render);
}

static void CreateVertexBuffer()
{
	Vector3f Vertices[4];
	LoadVector3(Vertices[0], -1.0f, -1.0f, 0.0f);
	LoadVector3(Vertices[1], 1.0f, -1.0f, 1.0f);
	LoadVector3(Vertices[2], 1.0f, -1.0f, 0.0f);
	LoadVector3(Vertices[3], 0.0f, 1.0f, 0.0f);

	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
static void CreateIndexBuffer()
{
	GLuint Indices[] = { 0,3,1,
					  1,3,2,
					  2,3,0,
					  0,1,2 };
	glGenBuffers(1, &IBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}

static void AdderShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
	GLuint ShaderObj = glCreateShader(ShaderType);
	if (!ShaderObj) {
		fprintf(stderr, "Error creating shader ype %d\n", ShaderType);
		system("pause");
		exit(1);
	}

	const GLchar* p[1];
	p[0] = pShaderText;
	GLint Lengths[1];
	Lengths[0] = strlen(pShaderText);
	glShaderSource(ShaderObj, 1, p, Lengths);
	glCompileShader(ShaderObj);
	GLint success;
	glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
	if (!success) {
		GLchar InfoLog[1024];
		glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
		fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
		system("pause");
		exit(1);
	}
	glAttachShader(ShaderProgram, ShaderObj);
}

static void CompileShaders()
{
	GLuint ShaderProgram = glCreateProgram();
	if (ShaderProgram == 0) {
		fprintf(stderr, "Error creating shader program\n");
		system("pause");
		exit(1);
	}

	string vs, fs;

	if (!ReadFile(pVSFileName, vs)) {
		exit(1);
	}
	if (!ReadFile(pFSFileName, fs)) {
		exit(1);
	}

	AdderShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
	AdderShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);

	GLint Success = 0;
	GLchar ErrorLog[1024] = { 0 };

	glLinkProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	glValidateProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	glUseProgram(ShaderProgram);

	gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld");
	assert(gWorldLocation != 0xFFFFFFFF);
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(10, 10);
	glutInitWindowSize(1024, 768);
	glutCreateWindow("Interpolation");

	InitializeGlutCallbacks();

	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
		system("pause");
		return 1;
	}

	printf("GL version: %s \n", glGetString(GL_VERSION));

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	CreateVertexBuffer();
	CreateIndexBuffer();
	CompileShaders();

	glutMainLoop();

	return 0;

}

OpenGL learning path 9 - mixed transformation

#include <stdio.h>
#include <string>
#include<math.h>
#define GLEW_STATIC
#include <gl/glew.h>
#include <gl/freeglut.h>
#include<fstream>
#include<assert.h>
#include "opengl_pipeline.h"
#include "opengl_math.h"

using namespace std;

GLuint VBO, IBO;
GLuint gWorldLocation;

const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";

bool ReadFile(const char* FileName, string &outFile)
{
	ifstream f(FileName);
	bool ret = false;

	if (f.is_open()) {
		string line;
		while (getline(f, line)) {
			outFile.append(line);
			outFile.append("\n");
		}
		f.close();
		ret = true;
	}
	else {
		fprintf(stderr, "%s:%d: unable to open file '%s'\n", __FILE__, __LINE__, FileName);
		system("pause");
	}
	return ret;
}

static void Render()
{
	glClear(GL_COLOR_BUFFER_BIT);

	static float Scale = 0.0f;
	Scale += 0.001f;

	//实例化一个Pipeline 
	Pipeline p;
	p.Scale(sinf(Scale*0.1f), sinf(Scale*0.1f), sinf(Scale*0.1f));
	p.WorldPos(sinf(Scale), 0.0f, 0.0f);
	p.Rotate(sinf(Scale)*90.0f, sinf(Scale)*90.0f, sinf(Scale)*90.0f);
	glUniformMatrix4fv(gWorldLocation, 1, GL_FALSE, (const GLfloat*)p.GetTrans());
	

	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);

	//绘制前绑定索引缓冲
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
	//索引绘制图形
	glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);

	glDisableVertexAttribArray(0);
	glutSwapBuffers();

}

static void InitializeGlutCallbacks()
{
	glutDisplayFunc(Render);
	glutIdleFunc(Render);
}

static void CreateVertexBuffer()
{
	Vector3f Vertices[4];
	LoadVector3(Vertices[0], -1.0f, -1.0f, 0.0f);
	LoadVector3(Vertices[1], 1.0f, -1.0f, 1.0f);
	LoadVector3(Vertices[2], 1.0f, -1.0f, 0.0f);
	LoadVector3(Vertices[3], 0.0f, 1.0f, 0.0f);

	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
static void CreateIndexBuffer()
{
	GLuint Indices[] = { 0,3,1,
					  1,3,2,
					  2,3,0,
					  0,1,2 };
	glGenBuffers(1, &IBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}

static void AdderShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
	GLuint ShaderObj = glCreateShader(ShaderType);
	if (!ShaderObj) {
		fprintf(stderr, "Error creating shader ype %d\n", ShaderType);
		system("pause");
		exit(1);
	}

	const GLchar* p[1];
	p[0] = pShaderText;
	GLint Lengths[1];
	Lengths[0] = strlen(pShaderText);
	glShaderSource(ShaderObj, 1, p, Lengths);
	glCompileShader(ShaderObj);
	GLint success;
	glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
	if (!success) {
		GLchar InfoLog[1024];
		glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
		fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
		system("pause");
		exit(1);
	}
	glAttachShader(ShaderProgram, ShaderObj);
}

static void CompileShaders()
{
	GLuint ShaderProgram = glCreateProgram();
	if (ShaderProgram == 0) {
		fprintf(stderr, "Error creating shader program\n");
		system("pause");
		exit(1);
	}

	string vs, fs;

	if (!ReadFile(pVSFileName, vs)) {
		exit(1);
	}
	if (!ReadFile(pFSFileName, fs)) {
		exit(1);
	}

	AdderShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
	AdderShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);

	GLint Success = 0;
	GLchar ErrorLog[1024] = { 0 };

	glLinkProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	glValidateProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	glUseProgram(ShaderProgram);

	gWorldLocation = glGetUniformLocation(ShaderProgram, "gWorld");
	assert(gWorldLocation != 0xFFFFFFFF);
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(10, 10);
	glutInitWindowSize(1024, 768);
	glutCreateWindow("Interpolation");

	InitializeGlutCallbacks();

	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
		system("pause");
		return 1;
	}

	printf("GL version: %s \n", glGetString(GL_VERSION));

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	CreateVertexBuffer();
	CreateIndexBuffer();
	CompileShaders();

	glutMainLoop();

	return 0;

}

OpenGL Learning Road 10----Perspective Projection

#include <stdio.h>
#include <string>
#include<math.h>
#define GLEW_STATIC
#include <gl/glew.h>
#include <gl/freeglut.h>
#include<fstream>
#include<assert.h>
#include "opengl_pipeline.h"
#include "opengl_math.h"

using namespace std;

GLuint VBO, IBO;
GLuint gWVPLocation;
PersProjInfo gPersProjInfo;

const char* pVSFileName = "shader.vs";
const char* pFSFileName = "shader.fs";

bool ReadFile(const char* FileName, string &outFile)
{
	ifstream f(FileName);
	bool ret = false;

	if (f.is_open()) {
		string line;
		while (getline(f, line)) {
			outFile.append(line);
			outFile.append("\n");
		}
		f.close();
		ret = true;
	}
	else {
		fprintf(stderr, "%s:%d: unable to open file '%s'\n", __FILE__, __LINE__, FileName);
		system("pause");
	}
	return ret;
}

static void Render()
{
	glClear(GL_COLOR_BUFFER_BIT);

	static float Scale = 0.0f;

	Scale += 0.1f;

	Pipeline p;
	p.Rotate(0.0f, Scale, 0.0f);
	p.WorldPos(0.0f, 0.0f, 3.0f);

	//相机变换
	Vector3f CameraPos, CameraTarget, CameraUp;
	LoadVector3(CameraPos, 0.0f, 0.0f, -4.0f);
	LoadVector3(CameraTarget, 0.0f, 0.0f, 1.0f);
	LoadVector3(CameraUp, 0.0f, 1.0f, 0.0f);
	p.SetCamera(CameraPos, CameraTarget, CameraUp);

	p.SetPerspectiveProj(gPersProjInfo);

	glUniformMatrix4fv(gWVPLocation, 1, GL_FALSE, (const GLfloat*)p.GetWVPTrans());

	glEnableVertexAttribArray(0);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);

	glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_INT, 0);

	glDisableVertexAttribArray(0);

	glutSwapBuffers();
}



static void InitializeGlutCallbacks()
{
	glutDisplayFunc(Render);
	glutIdleFunc(Render);
}

static void CreateVertexBuffer()
{
	Vector3f Vertices[4];
	LoadVector3(Vertices[0], -1.0f, -1.0f, 0.0f);
	LoadVector3(Vertices[1], 1.0f, -1.0f, 1.0f);
	LoadVector3(Vertices[2], 1.0f, -1.0f, 0.0f);
	LoadVector3(Vertices[3], 0.0f, 1.0f, 0.0f);

	glGenBuffers(1, &VBO);
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
}
static void CreateIndexBuffer()
{
	GLuint Indices[] = { 0,3,1,
					  1,3,2,
					  2,3,0,
					  0,1,2 };
	glGenBuffers(1, &IBO);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}

static void AdderShader(GLuint ShaderProgram, const char* pShaderText, GLenum ShaderType)
{
	GLuint ShaderObj = glCreateShader(ShaderType);
	if (!ShaderObj) {
		fprintf(stderr, "Error creating shader ype %d\n", ShaderType);
		system("pause");
		exit(1);
	}

	const GLchar* p[1];
	p[0] = pShaderText;
	GLint Lengths[1];
	Lengths[0] = strlen(pShaderText);
	glShaderSource(ShaderObj, 1, p, Lengths);
	glCompileShader(ShaderObj);
	GLint success;
	glGetShaderiv(ShaderObj, GL_COMPILE_STATUS, &success);
	if (!success) {
		GLchar InfoLog[1024];
		glGetShaderInfoLog(ShaderObj, 1024, NULL, InfoLog);
		fprintf(stderr, "Error compiling shader type %d: '%s'\n", ShaderType, InfoLog);
		system("pause");
		exit(1);
	}
	glAttachShader(ShaderProgram, ShaderObj);
}

static void ComileShaders()
{
	GLuint ShaderProgram = glCreateProgram();
	if (ShaderProgram == 0) {
		fprintf(stderr, "Error creating shader program\n");
		system("pause");
		exit(1);
	}

	string vs, fs;

	if (!ReadFile(pVSFileName, vs)) {
		exit(1);
	}
	if (!ReadFile(pFSFileName, fs)) {
		exit(1);
	}

	AdderShader(ShaderProgram, vs.c_str(), GL_VERTEX_SHADER);
	AdderShader(ShaderProgram, fs.c_str(), GL_FRAGMENT_SHADER);

	GLint Success = 0;
	GLchar ErrorLog[1024] = { 0 };

	glLinkProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_LINK_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Error linking shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	glValidateProgram(ShaderProgram);
	glGetProgramiv(ShaderProgram, GL_VALIDATE_STATUS, &Success);
	if (!Success) {
		glGetProgramInfoLog(ShaderProgram, sizeof(ErrorLog), NULL, ErrorLog);
		fprintf(stderr, "Invalid shader program: '%s'\n", ErrorLog);
		exit(1);
	}

	glUseProgram(ShaderProgram);

	gWVPLocation = glGetUniformLocation(ShaderProgram, "gWorld");
	assert(gWVPLocation != 0xFFFFFFFF);
}

int main(int argc, char **argv)
{
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
	glutInitWindowPosition(10, 10);
	glutInitWindowSize(1024, 768);
	glutCreateWindow("Interpolation");

	InitializeGlutCallbacks();

	GLenum res = glewInit();
	if (res != GLEW_OK) {
		fprintf(stderr, "Error: '%s'\n", glewGetErrorString(res));
		system("pause");
		return 1;
	}

	printf("GL version: %s \n", glGetString(GL_VERSION));

	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

	CreateVertexBuffer();
	CreateIndexBuffer();
	ComileShaders();

	gPersProjInfo.FOV = 30.0f;
	gPersProjInfo.Height = 768;
	gPersProjInfo.Width = 1024;
	gPersProjInfo.zNear = 1.0f;
	gPersProjInfo.zFar = 100.0f;


	glutMainLoop();

	return 0;

}

Guess you like

Origin blog.csdn.net/qq_41286356/article/details/115230699
Recommended