Hazel游戏引擎(103)实体的材质

文中若有代码、术语等错误,欢迎指正

前言

  • 前前言

    由于开发引擎,渲染是一部分,所以前期跳过了给实体附加材质功能,从而开发其它比较重要的部分,其它基础功能写好后,再回到渲染部分写好渲染代码是正确的选择。

    由于2D和3D的纹理不一样,所以要设计一个好的纹理系统

  • 目的

    为完成101节所说的拖动内容面板上的材质给实体,实体表面会显示这个材质

  • 如何实现

    同102节实现拖动场景文件到viewport视口一样

    1. 只需要在实体的属性面板上设置数据源
    2. 目标接受拖过来的文件路径
    3. 然后加载这个材质,再drawcall绘画出来

关键代码+代码流程

  • 在数据源上设置

    扫描二维码关注公众号,回复: 16210490 查看本文章
    void ContentBrowserPanel::OnImGuiRender()
    {
          
          			
        ImGui::PushStyleColor(ImGuiCol_Button, ImVec4(0, 0, 0, 0));// alpha为0 设置背景为无颜色
        ImGui::ImageButton((ImTextureID)icon->GetRendererID(), {
          
           thumbnailSize, thumbnailSize }, {
          
           0,1 }, {
          
           1,0 });// 1:ID,2:大小,3、4:左上角和右下角的uv坐标
        if (ImGui::BeginDragDropSource()) {
          
          
            ///
            // 数据源///
            // 这里设置拖动
            const wchar_t* itemPath = relativePath.c_str();
            ImGui::SetDragDropPayload("CONTENT_BROWSER_ITEM", itemPath, (wcslen(itemPath) + 1) * sizeof(wchar_t));
            ImGui::EndDragDropSource();
        }
    
  • 在拖动目标上设置

    void SceneHierarchyPanel::DrawComponents(Entity entity)
    	{
          
          // 实体SpriteRendererComponent组件		
    		// 完善UI:模板类画组件的ui
    		DrawComponent<SpriteRendererComponent>("Sprite Renderer", entity, [](auto& component)
    		{
          
          
    			ImGui::ColorEdit4("Color", glm::value_ptr(component.Color));
    
    			ImGui::Button("Texture", ImVec2(100.0f, 0.0f));
    			if (ImGui::BeginDragDropTarget()) {
          
          
    				if (const ImGuiPayload* payload = ImGui::AcceptDragDropPayload("CONTENT_BROWSER_ITEM")) {
          
          
    					const wchar_t* path = (const wchar_t*)payload->Data;
    					std::filesystem::path texturePath = std::filesystem::path(g_AssetPath) / path;
    					// 判断是不是纹理?或者创建好后。创建的时候会有断言
    					component.Texture = Texture2D::Create(texturePath.string());
    				}
    			}
    			ImGui::DragFloat("Tiling Factor", &component.TilingFactor, 0.1f, 0.0f, 100.0f);
    		});
    
  • editorlayer的update当前场景的update

    void EditorLayer::OnUpdate(Timestep ts)
    {
          
          
        m_ActiveScene->OnUpdateEditor(ts, m_EditorCamera);
    
  • 当前场景的update渲染物体

    void Scene::OnUpdateEditor(Timestep ts, EditorCamera& camera)
    {
          
          
        Renderer2D::BeginScene(camera);
        auto group = m_Registry.group<TransformComponent>(entt::get<SpriteRendererComponent>);
        for (auto entity : group) {
          
          
            auto [transform, sprite] = group.get<TransformComponent, SpriteRendererComponent>(entity);
            //Renderer2D::DrawQuad(transform.GetTransform(), sprite.Color, (int)entity);
            Renderer2D::DrawSprite(transform.GetTransform(), sprite, (int)entity);
        }
        Renderer2D::EndScene();
    }
    
  • Renderer2D调用drawcall绘制

    void Renderer2D::DrawSprite(const glm::mat4& transform, SpriteRendererComponent& src, int entityID)
    {
          
          
        if (src.Texture) {
          
          
            DrawQuad(transform, src.Texture, src.TilingFactor, src.Color, entityID);
        }
        else {
          
          
            DrawQuad(transform, src.Color, entityID);
        }
    }
    

效果

请添加图片描述

未来要修改shader系统

  • 问题讲述

    目前的shader系统有缓存,但是如果修改了glsl代码,系统没有感知源代码已经变了依旧会使用缓存,除非手动删除cache

    所以需要解决此问题

  • 解决方法

    将上一个源代码保存为hash存在文件中yaml格式

    当前源代码与保存的hash文件对比,如果相同就使用缓存,不相同就重新编译

Bug

效果图可见(最右边的纹理显示)有bug,批处理出了问题吧。。

  • 解决方法

    修改glsl代码,将glsl的接受TexIndex的变量移出struct就行了

    // Basic Texture Shader
    #type vertex
    #version 450 core
    layout(location = 0) in vec3 a_Position;
    layout(location = 1) in vec4 a_Color;
    layout(location = 2) in vec2 a_TexCoord;
    layout(location = 3) in float a_TexIndex;
    layout(location = 4) in float a_TilingFactor;
    layout(location = 5) in int a_EntityID;
    layout(std140, binding = 0) uniform Camera
    {
    	mat4 u_ViewProjection;
    };
    struct VertexOutput
    {
    	vec4 Color;
    	vec2 TexCoord;
    	//float TexIndex; // 移出struct
    	float TilingFactor;
    };
    layout(location = 0) out VertexOutput Output;
    
    // 重点/
    layout(location = 3) out flat float v_TexIndex; // 移到这里
    layout(location = 4) out flat int v_EntityID;
    void main()
    {
    	Output.Color = a_Color;
    	Output.TexCoord = a_TexCoord;
    	//Output.TexIndex = a_TexIndex;
    	v_TexIndex = a_TexIndex;
    	Output.TilingFactor = a_TilingFactor;
    	v_EntityID = a_EntityID;
    	gl_Position = u_ViewProjection * vec4(a_Position, 1.0);
    }
    #type fragment
    #version 450 core
    layout(location = 0) out vec4 color;
    layout(location = 1) out int color2;
    struct VertexOutput
    {
    	vec4 Color;
    	vec2 TexCoord;
    	//float TexIndex;
    	float TilingFactor;
    };
    layout(location = 0) in VertexOutput Input;
    layout(location = 3) in flat float v_TexIndex;
    layout(location = 4) in flat int v_EntityID;
    layout(binding = 0) uniform sampler2D u_Textures[32];
    void main()
    {
    	vec4 texColor = Input.Color;
    
    	//switch (int(Input.TexIndex))
    	switch (int(v_TexIndex))
    	{
    	case  0: texColor *= texture(u_Textures[0], Input.TexCoord * Input.TilingFactor); break;
    	......
    	}
    	color = texColor;
    	color2 = v_EntityID;
    }
    
  • 为什么

    因为若TexIndex在struct里面,从顶点阶段到fragment阶段,顶点的TexIndex值不变,但是两个顶点之间像素点它会成为线性插值后的值,如下:

    所以要把TexIndex移出外面用flat声明不用线性插值

猜你喜欢

转载自blog.csdn.net/qq_34060370/article/details/132265814