OpenGL 7.测试框架,批渲染

2023-11-13

测试功能基类

本节搭建一个简单的测试框架,实现在窗口上显示一个菜单栏,点击不同的选项,进入不同的功能。
在这里插入图片描述
附加目录中添加src,方便添加头文件。
新建目录如下:
在这里插入图片描述

测试基类 Test.h,测试菜单TestMenu,用于管理所有的测试

#pragma once

#include <functional>
#include <vector>
#include <string>
#include <iostream>

namespace test {
	class Test
	{
	public:
		Test(){}
		virtual ~Test(){}

		virtual void OnUpdate(float deltaTime){}
		virtual void OnRender(){}
		/// <summary>
		/// 使用ImGui绘制UI
		/// </summary>
		virtual void OnImGuiRender(){}
	};

	/// <summary>
	/// 包含所有测试的集合
	/// </summary>
	class TestMenu : public Test
	{
	public:
		TestMenu(Test*& currentTestPointer);

		void OnImGuiRender() override;

		template<typename T>
		void RegisterTest(const std::string& name) 
		{
			std::cout << "Registering test " << name << std::endl;
			//lambda函数
			m_Test.push_back(std::make_pair(name, []() { return new T(); }));
		}

	private:
		//当前测试,指针的引用
		Test*& m_CurrentTest;
		//测试名字,测试指针的函数
		std::vector<std::pair<std::string, std::function<Test*()>>> m_Test;
	};
}

Test.cpp

#include "Test.h"
#include "ImGui/imgui.h"

namespace test {

	TestMenu::TestMenu(Test*& currentTestPointer)
		: m_CurrentTest(currentTestPointer)
	{

	}

	void TestMenu::OnImGuiRender()
	{
		for (auto& test : m_Test) {
			if (ImGui::Button(test.first.c_str()))
				m_CurrentTest = test.second();
		}
	}

}

菜单项 – 修改窗口背景色

清除颜色,这里指修改背景色 TestClearColor.h

#pragma once

#include "Test.h"

namespace test {
	/// <summary>
	/// 清除颜色: 指的是用指定颜色填充背景色
	/// </summary>
	class TestClearColor : public Test
	{
	public:
		TestClearColor();
		~TestClearColor();

		void OnUpdate(float deltaTime) override;
		void OnRender() override;
		void OnImGuiRender() override;

	private:
		float m_ClearColor[4];
	};
}

TestClearColor.cpp

#include "TestClearColor.h"
#include "Renderer.h"
#include "imgui/imgui.h"

namespace test {
	TestClearColor::TestClearColor()
		:m_ClearColor{ 0.2f, 0.3f, 0.8f, 1.0f }
	{
	}

	TestClearColor::~TestClearColor()
	{
		GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
	}

	void TestClearColor::OnUpdate(float deltaTime)
	{
	}

	void TestClearColor::OnRender()
	{
		GLCall(glClearColor(m_ClearColor[0], m_ClearColor[1], m_ClearColor[2], m_ClearColor[3]));
		GLCall(glClear(GL_COLOR_BUFFER_BIT));
	}

	void TestClearColor::OnImGuiRender()
	{
		ImGui::ColorEdit4("ClearColor", m_ClearColor);
	}
}

菜单项 – 渲染贴图

这部分将之前写的渲染贴图的代码移动到单独的类中方便管理
TestTexture2D.h

#pragma once

#include "Test.h"
#include "VertexBuffer.h"
#include "VertexBufferLayout.h"
#include "Texture.h"
#include <memory>

namespace test {
	/// <summary>
	/// 渲染图片
	/// </summary>
	class TestTexture2D : public Test
	{
	public:
		TestTexture2D();
		~TestTexture2D();

		void OnUpdate(float deltaTime) override;
		void OnRender() override;
		void OnImGuiRender() override;

	private:
		//unique_ptr持有对对象的独有权,即两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作
		std::unique_ptr<VertexArray> m_VAO;
		std::unique_ptr<VertexBuffer> m_VertexBuffer;
		std::unique_ptr<IndexBuffer> m_IndexBuffer;
		std::unique_ptr<Shader> m_Shader;
		std::unique_ptr<Texture> m_Texture;
		glm::mat4 m_Proj, m_View;
		glm::vec3 m_TranslationA, m_TranslationB;
	};
}

TestTexture2D.cpp

#include "TestTexture2D.h"
#include "Renderer.h"

#include "imgui/imgui.h"

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

namespace test {
	TestTexture2D::TestTexture2D()
        : m_Proj(glm::ortho(0.0f, 960.0f, 0.0f, 540.0f, -1.0f, 1.0f)),
        m_View(glm::translate(glm::mat4(1.0f), glm::vec3(-100, 0, 0))),
        m_TranslationA(200, 200, 0), m_TranslationB(400, 200, 0)
	{
        float positions[] = {
            100.0f, 100.0f, 0.0f, 0.0f,//0
            200.0f, 100.0f, 1.0f, 0.0f,//1
            200.0f, 200.0f, 1.0f, 1.0f,//2
            100.0f, 200.0f, 0.0f, 1.0f,//3
        };

        unsigned int indices[] = {
            0, 1, 2,
            2, 3, 0,
        };

        //启用混合(默认不会启用)
        GLCall(glEnable(GL_BLEND));
        /**
         * glBlendFunc(src, dest) 指定颜色因子
         * src 指定输出颜色(RGBA)因子的计算方式, 默认为GL_ONE
         * dest 指定目标颜色因子的计算方式, 默认为GL_ZERO
         * GL_SRC_ALPHA 因为src的alpha为0, GL_ONE_MINUS_SRC_ALPHA 1-src.alpha
         * RGBA = Srgba * GL_SRC_ALPHA + Drgba * GL_ONE_MINUS_SRC_ALPHA
         **/
        GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
        GLCall(glBlendEquation(GL_FUNC_ADD));
        
        m_VAO = std::make_unique<VertexArray>();
        //4个顶点,每个顶点有4个浮点数
        m_VertexBuffer = std::make_unique<VertexBuffer>(positions, 4 * 4 * sizeof(float));
        VertexBufferLayout layout;
        layout.Push<float>(2);
        layout.Push<float>(2);
        m_VAO->AddBuffer(*m_VertexBuffer, layout);

        m_IndexBuffer = std::make_unique<IndexBuffer>(indices, 6);

        m_Shader = std::make_unique<Shader>(("res/shaders/Basic.shader"));
        m_Shader->Bind();

        m_Texture = std::make_unique<Texture>("res/textures/ChernoLogo.png");
        //纹理绑定到插槽0
        m_Shader->SetUniform1i("u_Texture", 0);
	}

	TestTexture2D::~TestTexture2D()
	{
		GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
	}

	void TestTexture2D::OnUpdate(float deltaTime)
	{
	}

	void TestTexture2D::OnRender()
	{
		GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
		GLCall(glClear(GL_COLOR_BUFFER_BIT));

        Renderer renderer;
        m_Texture->Bind();

        //绘制第一个icon
        {
            glm::mat4 model = glm::translate(glm::mat4(1.0f), m_TranslationA);
            glm::mat4 mvp = m_Proj * m_View * model;
            renderer.Draw(*m_VAO, *m_IndexBuffer, *m_Shader);
            m_Shader->SetUniformMat4f("u_MVP", mvp);
        }

        //修改mvp矩阵,绘制第二个icon
        {
            glm::mat4 model = glm::translate(glm::mat4(1.0f), m_TranslationB);
            glm::mat4 mvp = m_Proj * m_View * model;
            renderer.Draw(*m_VAO, *m_IndexBuffer, *m_Shader);
            m_Shader->SetUniformMat4f("u_MVP", mvp);
        }
	}

	void TestTexture2D::OnImGuiRender()
	{
        ImGui::SliderFloat3("Translation A", &m_TranslationA.x, 0.0f, 960.0f);
        ImGui::SliderFloat3("Translation B", &m_TranslationB.x, 0.0f, 960.0f);
        ImGui::Text("Application average %.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate, ImGui::GetIO().Framerate);
	}
}

菜单项 – 批渲染

批渲染是指将所有图形的顶点都放入同一个顶点缓冲区里,相应的扩大索引缓冲区,从而只绘制一次。
在这里插入图片描述
比如画两个正方形,如果不用批渲染
顶点缓冲区 = { position0, position1, position2, position3 }
索引缓冲区 = { 0, 1, 2, 2, 3, 0 }
渲染一个正方形就调用一次glDrawElements
在这里插入图片描述
使用批渲染
顶点缓冲区 = { position0, position1, position2, position3, position4, position5, position6, position7 }
索引缓冲区 = { 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4 }
调用一次glDrawElements就可以渲染两个正方形

下面是代码实现
TestBatchRender.h

#pragma once

#include "Test.h"
#include "VertexBuffer.h"
#include "VertexBufferLayout.h"
#include "Texture.h"
#include <memory>

namespace test {
	/// <summary>
	/// 批渲染
	/// </summary>
	class TestBatchRender : public Test
	{
	public:
		TestBatchRender();
		~TestBatchRender();

		void OnUpdate(float deltaTime) override;
		void OnRender() override;
		void OnImGuiRender() override;

	private:
		//unique_ptr持有对对象的独有权,即两个unique_ptr不能指向一个对象,不能进行复制操作只能进行移动操作
		std::unique_ptr<VertexArray> m_VAO;
		std::unique_ptr<VertexBuffer> m_VertexBuffer;
		std::unique_ptr<IndexBuffer> m_IndexBuffer;
		std::unique_ptr<Shader> m_Shader;
		std::unique_ptr<Texture> m_Textures[2];
		glm::mat4 m_Proj, m_View;
		glm::vec3 m_Translation;
		//控制第一个四边形左下角位置
		float m_QuadPosition[2] = { 100, 100 };
	};
}

TestBatchRender.cpp

#include "TestBatchRender.h"
#include "Renderer.h"
#include <array>

#include "imgui/imgui.h"

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

namespace test {

    struct Vec2
    {
        float x, y;
    };

    struct Vec3
    {
        float x, y, z;
    };

    struct Vec4
    {
        float x, y, z, w;
    };

    /// <summary>
    /// 顶点
    /// </summary>
    struct Vertex
    {
        Vec3 Position;
        Vec4 Color;
        Vec2 TexCoords; //纹理坐标
        float TexID;    //第几个插槽 
    };

    //最多四边形数量
    const unsigned int MaxQuadCount = 1000;
    //最大顶点数量
    const unsigned int MaxVertexCount = MaxQuadCount * 4;
    //最大索引缓冲区的数量
    const unsigned int MaxIndexCount = MaxQuadCount * 6;

    /// <summary>
    /// 创建四边形
    /// </summary>
    static Vertex* CreateQuad(Vertex* target, float x, float y, float textureID)
    {
        //边长
        float size = 100.0f;

        //以左下角是四边形原点
        target->Position = { x, y, 0.0f };
        target->Color = { 0.2f, 0.6f, 1.0f, 1.0f };
        target->TexCoords = { 0.0f, 0.0f };
        target->TexID = textureID;
        target++;

        target->Position = { x + size, y, 0.0f };
        target->Color = { 0.2f, 0.6f, 1.0f, 1.0f };
        target->TexCoords = { 1.0f, 0.0f };
        target->TexID = textureID;
        target++;

        target->Position = { x + size, y + size, 0.0f };
        target->Color = { 0.2f, 0.6f, 1.0f, 1.0f };
        target->TexCoords = { 1.0f, 1.0f };
        target->TexID = textureID;
        target++;

        target->Position = { x, y + size, 0.0f };
        target->Color = { 0.2f, 0.6f, 1.0f, 1.0f };
        target->TexCoords = { 0.0f, 1.0f };
        target->TexID = textureID;
        target++;

        return target;
    }

    TestBatchRender::TestBatchRender()
        : m_Proj(glm::ortho(0.0f, 960.0f, 0.0f, 540.0f, -1.0f, 1.0f)),
        m_View(glm::translate(glm::mat4(1.0f), glm::vec3(-100, 0, 0))),
        m_Translation(0, 0, 0)
	{
        //float vertices[] = {
        //    100.0f, 100.0f, 0.0f, 0.2f, 0.6f, 1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
        //    200.0f, 100.0f, 0.0f, 0.2f, 0.6f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f,
        //    200.0f, 200.0f, 0.0f, 0.2f, 0.6f, 1.0f, 1.0f, 1.0f, 1.0f, 0.0f,
        //    100.0f, 200.0f, 0.0f, 0.2f, 0.6f, 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,

        //    300.0f, 100.0f, 0.0f, 1.0f, 0.9f, 0.2f, 1.0f, 0.0f, 0.0f, 1.0f,
        //    400.0f, 100.0f, 0.0f, 1.0f, 0.9f, 0.2f, 1.0f, 1.0f, 0.0f, 1.0f,
        //    400.0f, 200.0f, 0.0f, 1.0f, 0.9f, 0.2f, 1.0f, 1.0f, 1.0f, 1.0f,
        //    300.0f, 200.0f, 0.0f, 1.0f, 0.9f, 0.2f, 1.0f, 0.0f, 1.0f, 1.0f,
        //};

        //unsigned int indices[] = {
        //    0, 1, 2, 2, 3, 0,
        //    4, 5, 6, 6, 7, 4
        //};

        unsigned int indices[MaxIndexCount];
        unsigned int offset = 0;
        for (unsigned int i = 0; i < MaxIndexCount; i += 6)
        {
            indices[i + 0] = 0 + offset;
            indices[i + 1] = 1 + offset;
            indices[i + 2] = 2 + offset;

            indices[i + 3] = 2 + offset;
            indices[i + 4] = 3 + offset;
            indices[i + 5] = 0 + offset;

            offset += 4;
        }

        GLCall(glEnable(GL_BLEND));
        GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
        GLCall(glBlendEquation(GL_FUNC_ADD));
        
        m_VAO = std::make_unique<VertexArray>();
        m_VertexBuffer = std::make_unique<VertexBuffer>(nullptr, sizeof(Vertex) * MaxVertexCount);
        VertexBufferLayout layout;
        layout.Push<float>(3); //坐标x y z
        layout.Push<float>(4); //颜色
        layout.Push<float>(2); //纹理坐标
        layout.Push<float>(1); //第几个纹理插槽
        m_VAO->AddBuffer(*m_VertexBuffer, layout);

        m_IndexBuffer = std::make_unique<IndexBuffer>(indices, MaxIndexCount);

        m_Shader = std::make_unique<Shader>(("res/shaders/Batch.shader"));
        m_Shader->Bind();

        m_Textures[0] = std::make_unique<Texture>("res/textures/ChernoLogo.png");
        m_Textures[1] = std::make_unique<Texture>("res/textures/HazelLogo.png");
        //纹理绑定到两个插槽上
        m_Textures[0]->Bind(0);
        m_Textures[1]->Bind(1);

        int samplers[2] = { 0, 1 };
        m_Shader->SetUniform1iv("u_Textures", 2, samplers);
	}

    TestBatchRender::~TestBatchRender()
	{
		GLCall(glClearColor(0.0f, 0.0f, 0.0f, 1.0f));
        GLCall(glBufferSubData(GL_ARRAY_BUFFER, 0, 0, nullptr));
        GLCall(glBufferData(GL_ARRAY_BUFFER, 0, nullptr, GL_DYNAMIC_DRAW));
	}

	void TestBatchRender::OnUpdate(float deltaTime)
	{
        std::array<Vertex, MaxVertexCount> vertices;
        Vertex* buffer = vertices.data();
        for (int y = 0; y < 500; y += 100) {
            for (int x = 300; x < 800; x += 100) {
                buffer = CreateQuad(buffer, x, y, (x + y) / 100 % 2);
            }
        }

        //创建一个可以移动的四边形
        buffer = CreateQuad(buffer, m_QuadPosition[0], m_QuadPosition[1], 0.0f);
        //每一帧,动态更新缓冲区数据
        glBufferSubData(GL_ARRAY_BUFFER, 0, vertices.size() * sizeof(Vertex), vertices.data());
	}

	void TestBatchRender::OnRender()
	{
		GLCall(glClearColor(0.6f, 1.0f, 1.0f, 1.0f));
		GLCall(glClear(GL_COLOR_BUFFER_BIT));

        Renderer renderer;

        glm::mat4 model = glm::translate(glm::mat4(1.0f), m_Translation);
        glm::mat4 mvp = m_Proj * m_View * model;
        renderer.Draw(*m_VAO, *m_IndexBuffer, *m_Shader);
        m_Shader->SetUniformMat4f("u_MVP", mvp);
	}

	void TestBatchRender::OnImGuiRender()
	{
        ImGui::Begin("Controls");
        ImGui::DragFloat2("Quad Position", m_QuadPosition, 0.1f);
        ImGui::End();
	}
}

为了支持动态修改顶点缓冲区,缓冲区使用类型改为动态
VertexBuffer.cpp

VertexBuffer::VertexBuffer(const void* data, unsigned int size)
{
    GLCall(glGenBuffers(1, &m_RendererID));
    GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID));
    //可以动态填充顶点缓冲区
    GLCall(glBufferData(GL_ARRAY_BUFFER, size, data, GL_DYNAMIC_DRAW));
}

为了支持批渲染,新增一个shader
Batch.shader

#shader vertex
#version 330 core

layout(location = 0) in vec4 a_Position;  //因为gl_Position是vec4,所有这里转换
layout(location = 1) in vec4 a_Color;     //顶点颜色
layout(location = 2) in vec2 a_TexCoord;  //纹理坐标
layout(location = 3) in float a_TexIndex; //第几个纹理

out vec4 v_Color;
out vec2 v_TexCoord;
out float v_TexIndex;

uniform mat4 u_MVP;

void main()
{
	//正交投影与顶点位置相乘,把它们转换到-1至1空间(NDC空间)
	gl_Position = u_MVP * a_Position;
	v_Color = a_Color;
    v_TexCoord = a_TexCoord;
	v_TexIndex = a_TexIndex;
};

#shader fragment
#version 330 core

layout(location = 0) out vec4 color;

in vec4 v_Color;
in vec2 v_TexCoord;
in float v_TexIndex;

//采样数组
uniform sampler2D u_Textures[2];

void main()
{
	int index = int(v_TexIndex);
	//从纹理上采样的颜色
	vec4 texColor = texture(u_Textures[index], v_TexCoord);
	color = texColor;
};

最后主程序
Application.cpp

#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include "Renderer.h"
#include "VertexBufferLayout.h"
#include "Texture.h"

#include "glm/glm.hpp"
#include "glm/gtc/matrix_transform.hpp"

#include "imgui/imgui.h"
#include "imgui/imgui_impl_glfw.h"
#include "imgui/imgui_impl_opengl3.h"

#include "tests/TestClearColor.h"
#include "tests/TestTexture2D.h"
#include "tests/TestBatchRender.h"

int main(void)
{
    GLFWwindow* window;

    if (!glfwInit())
        return -1;

    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
    glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);

    window = glfwCreateWindow(960, 540, "Hello World", NULL, NULL);
    if (!window)
    {
        glfwTerminate();
        return -1;
    }

    glfwMakeContextCurrent(window);

    glfwSwapInterval(1);

    GLenum err = glewInit();
    if (GLEW_OK != err)
        std::cout << err << std::endl;
    std::cout << glGetString(GL_VERSION) << std::endl;

    {
        GLCall(glEnable(GL_BLEND));
        GLCall(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
        GLCall(glBlendEquation(GL_FUNC_ADD));

        Renderer renderer;

        //创建上下文环境,初始化
        ImGui::CreateContext();
        ImGui_ImplGlfw_InitForOpenGL(window, true);
        ImGui::StyleColorsDark();

        //需要指定GLSL版本, 也就是shader中的version
        const char* glsl_version = "#version 330";
        ImGui_ImplOpenGL3_Init(glsl_version);

        test::Test* currentTest = nullptr;
        test::TestMenu* testMenu = new test::TestMenu(currentTest);
        //从菜单开始
        currentTest = testMenu;

        testMenu->RegisterTest<test::TestClearColor>("Clear Color");
        testMenu->RegisterTest<test::TestTexture2D>("2D Texture");
        testMenu->RegisterTest<test::TestBatchRender>("Batch Render");

        while (!glfwWindowShouldClose(window))
        {
            renderer.Clear();

            ImGui_ImplOpenGL3_NewFrame();
            ImGui_ImplGlfw_NewFrame();
            ImGui::NewFrame();

            if (currentTest)
            {
                currentTest->OnUpdate(0.0f);
                currentTest->OnRender();
                ImGui::Begin("Test");
                //当前不在测试菜单,而在某个具体的测试中,上面加个返回箭头
                if (currentTest != testMenu && ImGui::Button("<-"))
                {
                    delete currentTest;
                    currentTest = testMenu;
                }
                currentTest->OnImGuiRender();
                ImGui::End();
            }

            ImGui::Render();
            ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

            glfwSwapBuffers(window);
            glfwPollEvents();
        }

        delete currentTest;
        if (currentTest != testMenu)
            delete testMenu;
    }

    ImGui_ImplOpenGL3_Shutdown();
    ImGui_ImplGlfw_Shutdown();
    ImGui::DestroyContext();

    glfwDestroyWindow(window);
    glfwTerminate();
    return 0;
}

效果
在这里插入图片描述

参考代码:地址

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenGL 7.测试框架,批渲染 的相关文章

  • Qt 5 和 OS X Mavericks 问题

    我正在使用 Cmake 在 OS X 10 9 上构建 QT 项目 自 Mavericks 以来 OpenGL 标头的位置似乎发生了变化 文件夹 System Library Frameworks OpenGL framework Head
  • 对 VBO 中的特定三角形使用不同的纹理

    我有 9 个由三角形组成的四边形 如下所示 我在用着VBO存储有关它们的数据 它们的位置和纹理坐标 我的问题是 是否可以仅使用一个来使四边形 5 具有与其余四边形不同的纹理VBO and shader 绿色代表纹理 1 黄色代表纹理 2 到
  • 如何将 3D 图像输出到 3D 电视?

    我有一台 3D 电视 如果我不至少尝试让它显示我自己创作的漂亮 3D 图像 我就会逃避我的责任 作为一个极客 我之前已经完成了非常基本的 OpenGL 编程 因此我了解所涉及的概念 假设我可以为自己渲染一个简单的四面体或立方体并使其旋转一点
  • 哪个对缓存最友好?

    我试图很好地掌握面向数据的设计以及如何在考虑缓存的情况下进行最佳编程 基本上有两种情况我无法完全确定哪个更好以及为什么 是拥有一个对象向量更好 还是拥有对象原子数据的多个向量更好 A 对象向量示例 struct A GLsizei mInd
  • 在 OpenGL 中,为什么 glVertexAttribPointer 要求“指针”参数以 void* 形式传入?

    规格为glVertexAttribPointer如下 void glVertexAttribPointer GLuint index GLint size GLenum type GLboolean normalized GLsizei s
  • 法线在 openGL 中表现得很奇怪

    我一直在为 openGl 编写一个 obj 加载器 几何体加载得很好 但法线总是混乱的 我尝试在两个不同的程序中导出模型 但似乎没有任何效果 据我所知 这就是将法线放入 GL TRIANGLES 的方法 glNormal3fv norm1
  • 我的绘图存在坐标/glortho 问题

    I have made a bit of a change to my code in the last couple of hours as everything was messy with my grid so I made it i
  • 使用 Qt 在 xoverlay 之上绘制

    我希望在使用 Xoverlay 渲染的视频流之上绘制一些 UI 我正在使用 gstreamer 播放视频并使用 xoverlay 在 xvimagesink 上渲染它 我的小部件继承自 QGLWidget 我希望使用 QPainter 绘制
  • 如何将点光源转换为卵形/椭圆形?

    我希望通过具有不同 x 和 y 值的 vec2 半径将当前的圆形光变成椭圆形 有没有办法根据我当前在片段着色器中的代码来做到这一点 uniform struct Light vec4 colour vec3 position vec2 ra
  • Eclipse 标记 OpenGL 函数无法解析

    我尝试在 Eclipse C C 中使用一些 OpenGL 函数 一些 标准 函数如 GlClear 可以被 eclipse 识别 而其他函数如 glBindBuffer 和 glEnableVertexAttribArray 则不能 它们
  • 为什么 OpenGL 给对象提供句柄而不是指针?

    OpenGL 的传统是让用户使用 unsigned int 句柄来操作 OpenGL 对象 为什么不直接给出一个指针呢 与指针相比 唯一 ID 有何优点 TL DR OpenGL ID 不会双射映射到内存位置 单个 OpenGL ID 可能
  • OpenGL 与 Eclipse CDT + MinGW + GLEW + GLFW:未定义的参考

    Edit 与此同时 我已经弄清楚了这一点 并在下面写了详细的答案 我刚刚尝试在 Win7 上从 Express 版本的 MSVC 10 切换到 Eclipse CDT 在配置时遇到了以下简单 OpenGL 代码的问题 在 Visual St
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • 如果我用opengl绘图的话SDL Renderer就没用了吗?

    我正在学习 SDL2 但我也在使用使用 OpenGL 调用的 imgui 库 从我在网上各种博客上读到的内容来看 我无法轻松混合 SDL2 渲染器和 opengl 调用 我要么使用其中之一 要么使用另一个 我读过的大多数教程都使用渲染器 所
  • 为什么OpenGL使用float而不是double? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • OpenGL - 两个纹理的幂

    OpenGL 使用二次幂纹理 这是因为由于 MipMapping 某些 GPU 只接受 2 的幂纹理 当绘制比实际更大的纹理时 使用这些二次方纹理会导致问题 我想到了一种方法来解决这个问题 即仅在我们使纹理小于实际大小时使用 PO2 比率
  • Opengl 像素完美 2D 绘图

    我正在研究 2d 引擎 它已经工作得很好 但我不断收到像素错误 例如 我的窗口是 960x540 像素 我从 0 0 到 959 0 画一条线 我希望扫描线 0 上的每个像素都会被设置为一种颜色 但事实并非如此 最右边的像素没有被绘制 当我
  • 在 2D 纹理上绘制的红色矩形在绘制后立即消失

    跟随我的另一个问题 https stackoverflow com questions 18477291 render an outlined red rectangle on top a 2d texture in opengl 1847
  • 如何仅剪切剪切平面的交集(而不是并集)?

    在 OpenGL JOGL 中 当使用多个剪切平面时 似乎会应用所有剪切平面的并集 我想要的是路口要应用的所有剪裁平面 这可能吗 请参阅下面的简化二维示例 Edit An example of clipping by vertex shad
  • OpenGL 3.1 中已弃用 glLineStipple

    glLineStipple在最新的 OpenGL API 中已被弃用 它被替换成什么 如果不更换 怎样才能达到类似的效果呢 我当然不想使用兼容性配置文件 抱歉 它还没有被任何东西取代 我想到的第一个模拟它的想法是几何着色器 您向几何着色器提

随机推荐

  • 2019年9月25日星期三(STM32 ucos3)

    一 UCOS 1 概念 uc OS III Micro C OS Thee 微型C语言编写的操作系统第三版 是一个可升级 可固化 多任务基于优先级的可抢占式实时内核 ucos的任务个数不限制 实现了操作系统所需求的大部分功能 资源管理 同步
  • C++ 左值引用 和 右值引用

    C 左值引用 和 右值引用 左值 右值是什么 左值引用 右值引用 参考 总结 左值 右值是什么 表达式的分类图 mermaid svg eHEtnhMOW8UctFkd label font family trebuchet ms verd
  • StringBuffer内容清空效率比较

    在开发程序的时候 经常使用StringBuffer来进行字符串的拼接 如果在循环中来反复的做字符串拼接时 会清空Stringbuffer中的内容 然后再拼接新的字符串信息 例如 StringBuffer sb new StringBuffe
  • 刺激战场服务器无响应ios,绝地求生刺激战场IOS系统更新后玩不了 绝地求生刺激战场苹果手机更新后进不去...

    导 读 相信有不少的绝地求生刺激战场的IOS玩家们在本次的IOS系统更新后玩不了 这可让许多的苹果党们大为的苦恼 因此下面就来为各位针对绝地求生刺激战场苹果手机更新后进不去的问题做一个解决方案 希望能够帮到各 相信有不少的绝地求生刺激战场的
  • 基于VGG-Face的年龄估计(论文总结与代码解释)

    目录 1 本文改进 2 模型结构 3 训练模型 4 预测数据 5 实验结果 6 模型比较 7 结论分析 8 数据集分析 9 完整代码 1 本文改进 本文主要是使用VGG Face模型 卷积层不变 改变全连接层 在Adience数据库上进行年
  • 项目规模估计方法介绍

    项目成本估算是对完成项目工作所需要的 费用进行估计和计划 是 项目计划中的一个重要组成部分 要实行 成本控制 必须先估算 费用 费用估算过程实际上是确定完成项目全部工作活动所需要的资源的一个费用估计值 这是一个近似值 既可以用货币单位表示
  • http1 & http2 发展与特性

    Http http协议已经被广泛应用在web应用中 常用于一下几种场景 聊天 全双工 客户端和服务器实时通信 推送 服务器主动向客户端通信 应答 传统模式 客户端发起请求 服务器响应 长连接 TCP Http协议本身就是基于请求 应答模式的
  • Node.js(二十五)

    Node js 连接 MongoDB MongoDB是一种文档导向数据库管理系统 由C 撰写而成 本章节我们将为大家介绍如何使用 Node js 来连接 MongoDB 并对数据库进行操作 如果你还没有 MongoDB 的基本知识 可以参考
  • Oracle查询表占用的空间(表大小)

    Oracle查询表占用的空间 表大小 Oracle查询表占用的空间 表大小 一 方法一 使用dbms space包的object space usage函数来查表大小情况 二 方法二 查dba extents视图 三 方法三 查dba se
  • Android实现空间不够,自动换行

    复制粘贴修改文件名即可用 自己新建MyFlowLayout的java文件 package com example myapplication view import android content Context import androi
  • 前端Gzip优化

    gZip GZIP是网站压缩加速的一种技术 对于开启后可以加快我们网站的打开速度 原理是经过服务器压缩 客户端浏览器快速解压的原理 可以大大减少了网站的流量 在 http 1 0 协议中关于服务端发送的数据可以配置一个 Content En
  • DMNet复现(二)之模型篇:Density map guided object detection in aerial image

    以前用Swin Transformer Tiny训练了40epoch的 官方用的Faster RCNN 这里先用Swin Transformer Tiny进行测试 模型训练 采用基于MMDetection的框架Swin Transforme
  • I2C的C语言实现

    I2C的C语言实现 起始信号 停止信号 应答信号ACK与非应答信号NACK 等待ACK信号 发送一个字节 读取一个字节 单字节写入 读取 连续写入 读取 起始信号 当SCL为高期间 SDA由高到低的跳变 void I2C Start voi
  • 在Mac OS环境安装Composer

    简介 Composer 是 PHP 的一个依赖管理工具 安装流程 打开终端 输入下面指令 进入用户根目录 cd 执行安装指令 php r readfile https getcomposer org installer gt compose
  • 2023年数学建模:基于模拟退火算法的旅行商问题求解

    订阅专栏后9月比赛期间会分享思路及Matlab代码 目录 一 模拟退火算法的基本原理 二 实战案例 旅行商问题
  • YoloV8改进策略:新出炉的EMA注意力机制助力YoloV8更加强大

    本次改进使用最新的注意力机制EMA改进YoloV8 我们一起来看看效果吧 论文翻译 摘要 https arxiv org ftp arxiv papers 2305 2305 13563 pdf 在各种计算机视觉任务中 通道或空间注意力机制
  • Python3 数据挖掘系统搭建(四)

    上一节学习了数据清洗如何对内容去重 这一节继续学习一个完整的挖掘系统是怎么构建的 以搜索百度新闻数据为例 首先要建立评分系统需要创建一个数据表 起名为article吧 字段如下图 字段有company title href source d
  • 6-Mysql子查询,多表连接(内连接,外连接,交叉连接)

    子查询 select from 学生表 查询高技2班的学生信息 select from 班级表 1 子查询当做查询条件的一部分 select from 学生表 where 班级ID in select 班级ID from 班级表 where
  • java heap space默认值_java heap space解决方法

    java heap space解决方法 在JVM中如果98 的时间是用于GC Garbage Collection 且可用的 Heap size 不足2 的时候将抛出异常信息 java lang OutOfMemoryError Java
  • OpenGL 7.测试框架,批渲染

    测试功能基类 本节搭建一个简单的测试框架 实现在窗口上显示一个菜单栏 点击不同的选项 进入不同的功能 附加目录中添加src 方便添加头文件 新建目录如下 测试基类 Test h 测试菜单TestMenu 用于管理所有的测试 pragma o