OpenGL学习之路1----打开一个窗口

新建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学习之路2----画一个点

新建opengl_math.h 内容如下

#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

main.cpp  内容如下

#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;
}

画3个点的时候需要glEnableVertexAttribArray(0)函数

#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学习之路3----画一个三角形

#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;
}

画带有颜色的三角形需要glColor3f函数,纯色填充

#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学习之路4----使用着色器(shader)

顶点着色器决定要绘制图形的位置,片元着色器决定要绘制图形的颜色

新建shader.vs顶点着色器

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

新建shader.fs片元着色器

#version 330

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

这节的main.cpp写了很多。编译GLSL写的着色器、并运行

#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学习之路5----使用一致变量(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学习之路7----插值

一个有多个颜色的三角形

#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学习之路8----索引绘制

#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学习之路9----混合变换

#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学习之路10----透视投影

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

}