OPENGL学习(五)Modern OpenGL 三角形绘制

和传统opengl相比,主要差别就是需要手写着色器,具体看这篇添加链接描述
底下是我的中文注释版

把shader写入main中

#include <iostream>

// GLEW
#define GLEW_STATIC //链接静态库需要宏定义
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>

// Window size
const int Width = 800, Height = 600;

// 当用户按下ESC键,我们设置window窗口的WindowShouldClose属性为true,关闭应用程序
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(window, GL_TRUE);
}

// Shaders
const GLchar* vertexShaderSource = "#version 330 core\n"
	"layout (location = 0) in vec3 position;\n"
	"void main()\n"
	"{\n"
	"gl_Position = vec4(position.x, position.y, position.z, 1.0);\n"
	"}\0";
const GLchar* fragmentShaderSource = "#version 330 core\n"
	"out vec4 color;\n"
	"void main()\n"
	"{\n"
	"color = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
	"}\n\0";



int main(int argc, char** argv)
{
	// Init GLFW
	glfwInit();
	// 设置opengl基本设置
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//最高版本
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//最低版本
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//Core file
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);//不可以调整窗口大小

	// 创建窗口
	GLFWwindow* window = glfwCreateWindow(Width, Height, "A Triangle", nullptr, nullptr);
	glfwMakeContextCurrent(window);

	// 绑定按键回调函数
	glfwSetKeyCallback(window, key_callback);

	// 开启modern opengl
	glewExperimental = GL_TRUE;

	// 初始化glew(modern opengl)
	glewInit();

	// 设置窗口大小
	int width, height;
	glfwGetFramebufferSize(window, &width, &height);
	glViewport(0, 0, width, height);

    // Vertex shader
	GLuint vertexShader = glCreateShader(GL_VERTEX_SHADER);
	// 绑定源文件,第一个创建的着色器,第二个是绑定了多少个glsl,第三个是glsl源文件
	// 最后一个是每个段占多少字符,因为就一个文件,所以可以不填
	glShaderSource(vertexShader, 1, &vertexShaderSource, NULL);
	// 编译着色器对象
	glCompileShader(vertexShader);
	// 处理error
	// 因为着色器很可能会写错,而着色器出错的log需要手动输出
	GLint success;
	GLchar infoLog[512];
	glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
	}

	// Fragment shader
	GLuint fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
	glShaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
	glCompileShader(fragmentShader);
	// Check for compile time errors
	glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
	if (!success)
	{
		glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
	}

	// 链接 shaders
	GLuint shaderProgram = glCreateProgram();
	glAttachShader(shaderProgram, vertexShader);
	glAttachShader(shaderProgram, fragmentShader);
	glLinkProgram(shaderProgram);
	// Check for linking errors
	glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
	if (!success) {
		glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
		std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
	}
	// 删除着色器对象
	glDeleteShader(vertexShader);
	glDeleteShader(fragmentShader);

	// 顶点buffer
	GLfloat vertices[] = {
		-0.5f, -0.5f, 0.0f,   
		 0.5f, -0.5f, 0.0f, 
		 0.0f,  0.5f, 0.0f
	};

	// VAO:Vertex Array Object
	// 其实就是索引,因为可能会有很多不同的VBO,如果每个都生成一个索引太麻烦
	// VBO:vertex buffer object
	// 每个vertex的具体数据
	GLuint VBO, VAO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	// 绑定VAO
	glBindVertexArray(VAO);

	// 绑定VBO
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	// 绑定数组
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// 确定VAO具体参数
	// 第一个参数是着色器中的layout,即这个数组对应着色器中的哪个属性
	// 第二个参数是指定顶点属性大小,代表一个顶点三个数字vec3
	// 第三个参数是数据类型
	// 第四个参数确定是否将数据映射到0-1之间
	// 第五个参数是步长,代表下一个数据在多少byte之后
	// 第六个数据是偏移量,即数组开始的位置
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
	// 开启VAO,参数是index,这个index其实就是绑定的VBO的layout
	glEnableVertexAttribArray(0);

	// 我觉得应该是VAO已经通过VBO绑定了,只有在更换VBO的时候才需要换绑
	glBindBuffer(GL_ARRAY_BUFFER,0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind
	// 可能绑定时会产生什么奇怪的状态导致出错,最好只在绘制时绑定
	glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs)

	// main loop
	while (!glfwWindowShouldClose(window))
	{
		// 轮询事件
		glfwPollEvents();

		// 清空颜色
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		// 使用编译好的着色器程序
		glUseProgram(shaderProgram);
		// 绑定VAO
		glBindVertexArray(VAO);
		//绘制三角形,第二个参数是数组起始位置,第三个参数是定点数量
		glDrawArrays(GL_TRIANGLES, 0, 3);
		glBindVertexArray(0);

		// double buffer
		glfwSwapBuffers(window);
	}
	// 删除VAO和VBO
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	// 释放窗口资源
	glfwTerminate();
	return 0;
}

额外使用写一个shader类帮忙读取着色器

main:

#include <iostream>

#include <shader.h>

// GLEW
#include <GL/glew.h>

// GLFW
#include <GLFW/glfw3.h>

// Window size
const int Width = 800, Height = 600;

// 当用户按下ESC键,我们设置window窗口的WindowShouldClose属性为true,关闭应用程序
void key_callback(GLFWwindow* window, int key, int scancode, int action, int mode)
{
	if (key == GLFW_KEY_ESCAPE && action == GLFW_PRESS)
		glfwSetWindowShouldClose(window, GL_TRUE);
}




int main(int argc, char** argv)
{
	// Init GLFW
	glfwInit();
	// 设置opengl基本设置
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//最高版本
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//最低版本
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);//Core file
	glfwWindowHint(GLFW_RESIZABLE, GL_FALSE);//不可以调整窗口大小

	// 创建窗口
	GLFWwindow* window = glfwCreateWindow(Width, Height, "A Triangle", nullptr, nullptr);
	glfwMakeContextCurrent(window);

	// 绑定按键回调函数
	glfwSetKeyCallback(window, key_callback);

	// 开启modern opengl
	glewExperimental = GL_TRUE;

	// 初始化glew(modern opengl)
	glewInit();

	// 设置窗口大小
	int width, height;
	glfwGetFramebufferSize(window, &width, &height);
	glViewport(0, 0, width, height);

	Shader ourShader("Shaders/shader.vert", "Shaders/shader.frag");

	// 顶点buffer
	GLfloat vertices[] = {
		-0.5f, -0.5f, 0.0f,
		 0.5f, -0.5f, 0.0f,
		 0.0f,  0.5f, 0.0f
	};

	// VAO:Vertex Array Object
	// 其实就是索引,因为可能会有很多不同的VBO,如果每个都生成一个索引太麻烦
	// VBO:vertex buffer object
	// 每个vertex的具体数据
	GLuint VBO, VAO;
	glGenVertexArrays(1, &VAO);
	glGenBuffers(1, &VBO);
	// 绑定VAO
	glBindVertexArray(VAO);

	// 绑定VBO
	glBindBuffer(GL_ARRAY_BUFFER, VBO);
	// 绑定数组
	glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);

	// 确定VAO具体参数
	// 第一个参数是着色器中的layout,即这个数组对应着色器中的哪个属性
	// 第二个参数是指定顶点属性大小,代表一个顶点三个数字vec3
	// 第三个参数是数据类型
	// 第四个参数确定是否将数据映射到0-1之间
	// 第五个参数是步长,代表下一个数据在多少byte之后
	// 第六个数据是偏移量,即数组开始的位置
	glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(GLfloat), (GLvoid*)0);
	// 开启VAO,参数是index,这个index其实就是绑定的VBO的layout
	glEnableVertexAttribArray(0);

	// 我觉得应该是VAO已经通过VBO绑定了,只有在更换VBO的时候才需要换绑
	glBindBuffer(GL_ARRAY_BUFFER, 0); // Note that this is allowed, the call to glVertexAttribPointer registered VBO as the currently bound vertex buffer object so afterwards we can safely unbind
	// 可能绑定时会产生什么奇怪的状态导致出错,最好只在绘制时绑定
	glBindVertexArray(0); // Unbind VAO (it's always a good thing to unbind any buffer/array to prevent strange bugs)

	// main loop
	while (!glfwWindowShouldClose(window))
	{
		// 轮询事件
		glfwPollEvents();

		// 清空颜色
		glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		// 使用编译好的着色器程序
		ourShader.Use();
		// 绑定VAO
		glBindVertexArray(VAO);
		//绘制三角形,第二个参数是数组起始位置,第三个参数是定点数量
		glDrawArrays(GL_TRIANGLES, 0, 3);
		glBindVertexArray(0);

		// double buffer
		glfwSwapBuffers(window);
	}
	// 删除VAO和VBO
	glDeleteVertexArrays(1, &VAO);
	glDeleteBuffers(1, &VBO);
	// 释放窗口资源
	glfwTerminate();
	return 0;
}

shader.vertx

#version 330 core
layout (location = 0) in vec3 position;
void main()
{
	gl_Position = vec4(position.x, position.y, position.z, 1.0);
};

shader.frag

#version 330 core
out vec4 color;
void main()
{
	color = vec4(1.0f, 0.5f, 0.2f, 1.0f);
}

shader.h

#pragma once
#ifndef SHADER_H
#define SHADER_H

#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

#include <GL/glew.h>

class Shader
{
public:
    GLuint Program;
    // Constructor generates the shader on the fly
    Shader(const GLchar* vertexPath, const GLchar* fragmentPath)
    {
        // 1. Retrieve the vertex/fragment source code from filePath
        std::string vertexCode;
        std::string fragmentCode;
        std::ifstream vShaderFile;
        std::ifstream fShaderFile;
        // ensures ifstream objects can throw exceptions:
        vShaderFile.exceptions(std::ifstream::badbit);
        fShaderFile.exceptions(std::ifstream::badbit);
        try
        {
            // Open files
            vShaderFile.open(vertexPath);
            fShaderFile.open(fragmentPath);
            std::stringstream vShaderStream, fShaderStream;
            // Read file's buffer contents into streams
            vShaderStream << vShaderFile.rdbuf();
            fShaderStream << fShaderFile.rdbuf();
            // close file handlers
            vShaderFile.close();
            fShaderFile.close();
            // Convert stream into string
            vertexCode = vShaderStream.str();
            fragmentCode = fShaderStream.str();
        }
        catch (std::ifstream::failure e)
        {
            std::cout << "ERROR::SHADER::FILE_NOT_SUCCESFULLY_READ" << std::endl;
        }
        const GLchar* vShaderCode = vertexCode.c_str();
        const GLchar* fShaderCode = fragmentCode.c_str();
        // 2. Compile shaders
        GLuint vertex, fragment;
        GLint success;
        GLchar infoLog[512];
        // Vertex Shader
        vertex = glCreateShader(GL_VERTEX_SHADER);
        glShaderSource(vertex, 1, &vShaderCode, NULL);
        glCompileShader(vertex);
        // Print compile errors if any
        glGetShaderiv(vertex, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(vertex, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
        }
        // Fragment Shader
        fragment = glCreateShader(GL_FRAGMENT_SHADER);
        glShaderSource(fragment, 1, &fShaderCode, NULL);
        glCompileShader(fragment);
        // Print compile errors if any
        glGetShaderiv(fragment, GL_COMPILE_STATUS, &success);
        if (!success)
        {
            glGetShaderInfoLog(fragment, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
        }
        // Shader Program
        this->Program = glCreateProgram();
        glAttachShader(this->Program, vertex);
        glAttachShader(this->Program, fragment);
        glLinkProgram(this->Program);
        // Print linking errors if any
        glGetProgramiv(this->Program, GL_LINK_STATUS, &success);
        if (!success)
        {
            glGetProgramInfoLog(this->Program, 512, NULL, infoLog);
            std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
        }
        // Delete the shaders as they're linked into our program now and no longer necessery
        glDeleteShader(vertex);
        glDeleteShader(fragment);

    }
    // Uses the current shader
    void Use()
    {
        glUseProgram(this->Program);
    }
};

#endif
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个OpenGL程序,用于绘制多个不同颜色的三角形: ```c++ #include <GL/glut.h> void init() { glClearColor(0.0, 0.0, 0.0, 0.0); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluOrtho2D(0.0, 500.0, 0.0, 500.0); } void display() { glClear(GL_COLOR_BUFFER_BIT); // 绘制第一个三角形,红色 glColor3f(1.0, 0.0, 0.0); glBegin(GL_TRIANGLES); glVertex2f(100.0, 100.0); glVertex2f(200.0, 100.0); glVertex2f(150.0, 200.0); glEnd(); // 绘制第二个三角形,绿色 glColor3f(0.0, 1.0, 0.0); glBegin(GL_TRIANGLES); glVertex2f(250.0, 250.0); glVertex2f(350.0, 250.0); glVertex2f(300.0, 350.0); glEnd(); // 绘制第三个三角形,蓝色 glColor3f(0.0, 0.0, 1.0); glBegin(GL_TRIANGLES); glVertex2f(400.0, 100.0); glVertex2f(450.0, 200.0); glVertex2f(500.0, 100.0); glEnd(); glFlush(); } int main(int argc, char** argv) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB); glutInitWindowSize(500, 500); glutCreateWindow("Multiple Triangles"); init(); glutDisplayFunc(display); glutMainLoop(); return 0; } ``` 该程序使用了OpenGL的基本绘图函数来绘制三个不同颜色的三角形。在每个三角形之前,我们使用glColor3f函数来设置绘制颜色。然后使用glBegin和glEnd函数来指定绘制的几何图形的类型(在这里是三角形)和顶点。在每个三角形中,我们指定了三个顶点的坐标。最后,我们使用glFlush函数强制将绘制的图形显示在屏幕上。 运行该程序,您将看到窗口中绘制了三个不同颜色的三角形

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值