【Cherno的OpenGL视频】Writing a basic Renderer in OpenGL

本文介绍了渲染器在图形编程中的作用,通过创建一个渲染器类并实现Draw函数,将数据传送到屏幕上。同时,讨论了OpenGL中解绑资源的必要性和性能影响。在实践中,为避免头文件循环包含问题,对文件结构进行了调整。最后,解释了材料(Material)的概念,作为Shader和其 uniforms 的组合,用于简化渲染过程。
摘要由CSDN通过智能技术生成

1、What is a renderer?
The renderer is like the factory where we could say “hey here are some parts I want you to make something for me.” Now we have a bunch of data in the form of like a vertex buffer index buffer a shader…and we want to be able to give that data to someone and say “hey this stuff that I’m giving you I want it to appear in the screen please”, that’s kind of what the job of a renderer is.
So our goal for today is really just to move away the last remaining draw call that we have inside our main file(code below.).

			/* Render here */
			GLCall(glClear(GL_COLOR_BUFFER_BIT));

			shader.Bind();
			shader.SetUniform4f("u_Color", r, 0.3f, 0.8f, 1.0f);

			VA.Bind();
			IB.Bind();

			GLCall(glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr));

2、How are we gonna do that?
Making a renderer class and inside that class we’re going to be writing a draw function which
basically takes in a bunch of parameters so the data that actually needs to draw something and
then draws in on the screen.
From that approach even though that might seem like a really
simple thing we can grow that into something extremely complex and extremely powerful.

3、Unbinding in OpenGL
Unbinding stuff in OpenGL is not strictly necessary, it is useful for debugging but it might reduce
some bugs maybe, still ultimately speaking unbinding stuff in OpenGL is a waste of performance.
We don’t really need to do that because before we draw the next thing we’ll be binding all this
stuff anyway, more kind of complex systems might have unbinding in debug mode and then in
release mode the unbind calls just do nothing that’s one option.
For learning OpenGL purpose, we don’t really care about performance or anything like that.

4、代码实现:
之前的Renderer类中添加Clear()和Draw()。
在这里插入图片描述
Application.cpp

#include <GL/glew.h>// 放在glfw3.h之前,或者任何OpenGL之前。
#include <GLFW/glfw3.h>
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

#include "Renderer.h"
#include "VertexBuffer.h"
#include "IndexBuffer.h"
#include "VertexArray.h"
#include "Shader.h"
#include "VertexBufferLayout.h"

int main(void)
{
	GLFWwindow* window;

	/* Initialize the library */
	if (!glfwInit())
		return -1;

	// 指定用3.3.0版本。
	glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);//3.0
	glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);//0.3  
	// Setting my OpenGL profile to be core!!
	glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

	/* Create a windowed mode window and its OpenGL context */
	window = glfwCreateWindow(640, 640, "I am Groot", NULL, NULL);
	if (!window)
	{
		glfwTerminate();
		return -1;
	}

	/* Make the window's context current */
	glfwMakeContextCurrent(window);

	glfwSwapInterval(1);

	// after glfwMakeContextCurrent() -> Testing GLEW.
	if (glewInit() != GLEW_OK)
	{
		std::cout << "glewInit() error" << std::endl;
	}
	std::cout << glGetString(GL_VERSION) << std::endl;
	// Testing GLEW.

	{
		// on the CPU.
		float positions[] = {
			-0.5f, -0.5f, //index0
			 0.5f, -0.5f, //index1
			 0.5f,  0.5f, //index2
			-0.5f,  0.5f, //index3
		};

		// on the CPU.
		unsigned int indices[] = {
			0, 1, 2,//index0 1 2
			2, 3, 0 //index2 3 0
		};

		// Create a vertex array object.
		VertexArray VA;

		// Define a vertex buffer: send positions to GPU.
		VertexBuffer VB(positions, 4 * 2 * sizeof(float));

		// set up the layout for it.
		VertexBufferLayout layout;
		layout.Push<float>(2);
		VA.AddBuffer(VB, layout);

		// Define a index buffer: send indices to GPU.
		IndexBuffer IB(indices, 6);

		// Use our shader.
		Shader shader("res/shaders/Basic.shader");
		shader.Bind();
		shader.SetUniform4f("u_Color", 0.8f, 0.3f, 0.8f, 1.0f);

		// Unbinding everything.
		VA.Unbind();
		VB.Unbind();
		IB.Unbind();
		shader.Unbind();

		// Renderer.
		Renderer renderer;

		// sth for fun.
		float r = 0.0f;
		float increment = 0.05f;
		// sth for fun.

		/* Loop until the user closes the window */
		while (!glfwWindowShouldClose(window))
		{
			/* Render here */
			renderer.Clear();

			shader.Bind();
			// a material is basically a shader plus all of it's uniforms.
			shader.SetUniform4f("u_Color", r, 0.3f, 0.8f, 1.0f);

			renderer.Draw(VA, IB, shader);

			if (r > 1.0f)
			{
				increment = -0.05f;
			}
			else if (r < 0.0f)
			{
				increment = 0.05f;
			}
			r += increment;

			/* Swap front and back buffers */
			glfwSwapBuffers(window);

			/* Poll for and process events */
			glfwPollEvents();
		}
	}
	glfwTerminate();
	return 0;
}

5、遇到的错误:
在这里插入图片描述
原因:头文件互相包含了,VertexArray.h包含了Renderer.h, Renderer.h里包含了VertexArray.h.
解决:VertexArray.h去掉包含"VertexBufferLayout.h",添加class VertexBufferLayout;
VertexArray.cpp包含"VertexBufferLayout.h".

6、运行结果:

Something Fun

7、What is a material?
Right now our renderer’s Draw() function is taking in vertex buffer index buffer and a shader, but
in a more traditional setup we’d be taking in vertex array and index buffer and a material instead
of an actual shader, a material is basically a shader plus a set of data, a shader plus all of it’s
uniforms, whether that be kind of render a specific uniforms or kind of per object uniforms
(like: our square), so in that way when we pass in the material to the render, it’ll basically bind
the material, means it’ll bind the shader and set up all the uniforms that it needs to and then
call the draw function for our vertex array index buffer and all that stuff.
So now if we want to modify a uniform for a shader we have to do it manually.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值