OpenGL红宝书第一个例子:绘制两个三角形
1. 环境配置
在这里不在做环境配置的说明,因为网上可以找到很多类似的教程,如果有需要可以@我,我也希望能帮到大家,其它的不说了,先上我的代码
2. 第一个程序代码
- 创建LoadShader.h
#pragma once
#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <string>
GLuint LoadShader(const char *vertice_path, const char *framgment_path);
bool compileShader(GLuint &shader_id, const char *path);
static const GLchar *getFileData(const char * path);
- 创建LoadShader.cpp
#include "LoadShader.h"
#include <fstream>
#include <vector>
GLuint LoadShader( const char *vertice_path, const char *framgment_path )
{
GLuint vertexShaderID = glCreateShader(GL_VERTEX_SHADER);
GLuint fragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
bool bRet = compileShader(vertexShaderID, vertice_path);
if(!bRet)
return 0;
bRet = compileShader(fragmentShaderID, framgment_path);
if(!bRet)
return 0;
GLuint ProgramID = glCreateProgram();
glAttachShader(ProgramID, vertexShaderID);
glAttachShader(ProgramID, fragmentShaderID);
glLinkProgram(ProgramID);
glDeleteShader(vertexShaderID);
glDeleteShader(fragmentShaderID);
return ProgramID;
}
static const GLchar* getFileData( const char * path )
{
FILE* infile;
fopen_s(&infile, path, "rb");
if(!infile)
{
return NULL;
}
fseek(infile, 0, SEEK_END);
int len = ftell(infile);
fseek(infile, 0, SEEK_SET);
GLchar *source = new GLchar[len + 1];
fread(source, 1, len, infile);
fclose(infile);
source[len] = 0;
return const_cast<const GLchar *>(source);
}
bool compileShader( GLuint &shader_id, const char *path )
{
const GLchar *shader_code = getFileData(path);
if(strlen(shader_code) <= 0 )
return 0;
GLint Result = GL_FALSE;
GLint InfoLogLength;
glShaderSource(shader_id, 1, &shader_code, NULL);
glCompileShader(shader_id);
delete []shader_code;
glGetShaderiv(shader_id, GL_COMPILE_STATUS, &Result);
if ( !Result ){
glGetShaderiv(shader_id, GL_INFO_LOG_LENGTH, &InfoLogLength);
std::vector<char> ShaderErrorMessage(InfoLogLength+1);
glGetShaderInfoLog(shader_id, InfoLogLength, NULL, &ShaderErrorMessage[0]);
printf("%s\n", &ShaderErrorMessage[0]);
return false;
}
return true;
}
- OpenGL主逻辑文件triangles.cpp
#include <iostream>
#include "LoadShader.h"
GLFWwindow *window;
enum VAO_IDs { Triangles, NumVAOs };
enum Buffer_IDs { ArrayBuffer, NumBuffers };
enum Attrib_IDs { vPosition = 0 };
GLuint VAOs[NumVAOs];
GLuint Buffers[NumBuffers];
const GLuint NumVertices = 6;
GLuint shader_program;
void init()
{
glGenVertexArrays(NumVAOs,VAOs);
glBindVertexArray(VAOs[Triangles]);
GLfloat vertices[NumVertices][2] = {
{ -0.90f, -0.90f },
{ 0.85f, -0.90f },
{ -0.90f, 0.85f },
{ 0.90f, -0.85f },
{ 0.90f, 0.90f },
{ -0.85f, 0.90f }
};
glGenBuffers(NumVertices, Buffers);
glBindBuffer(GL_ARRAY_BUFFER, Buffers[ArrayBuffer]);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
shader_program = LoadShader("triangles.vert", "triangles.frag");
glUseProgram(shader_program);
glVertexAttribPointer(vPosition, 2, GL_FLOAT, GL_FALSE, 0, (void *)0);
glEnableVertexAttribArray(vPosition);
}
void display()
{
while (!glfwWindowShouldClose(window))
{
/* Render here */
glClear(GL_COLOR);
glBindVertexArray(VAOs[Triangles]);
glDrawArrays(GL_TRIANGLES, 0, NumVertices);
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
}
int main(int argc, char** argv)
{
if(!glfwInit())
return -1;
glfwWindowHint(GLFW_SAMPLES, 4);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
window = glfwCreateWindow(512, 512, "Hello World", NULL, NULL);
if(!window)
{
glfwTerminate();
return -1;
}
glfwMakeContextCurrent(window);
// Initialize GLEW
glewExperimental = true; // Needed for core profile
if( GLEW_OK != glewInit())
return -1;
init();
display();
return 0;
}
- 顶点shader
#version 330 core
// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec4 vPosition;
void main(){
gl_Position = vPosition;
}
- 片段shader
#version 330 core
// Ouput data
out vec4 fcolor;
void main()
{
fcolor = vec4(0.0, 0.0, 1.0, 1.0);
}
3.我在编写程序的时候遇到的问题
3.1 因为例子是用4.3的,在我电脑上我用glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
设置后就会失败,后来改成了3.3就成功了,不知道原因,我猜测可能我的电脑不支持4.3的OpenGL
3.2 写shader加载的时候遇到了点问题,glGetShaderiv(shader_id, GL_COMPILE_STATUS, &Result);
没有看仔细glGetShaderiv
的参数说明:Result正确的时候返回的是true,否则返回false,程序写反了,所以一直加载shader失败
第一个OpenGL程序到这里就结束了。后续努力中。。。
注: 后续的shader加载就不在说明,只有在添加的时候新内容的时候才会再次说明