<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                上一節我們自己寫好了一個數學庫,以供使用。 接下來,我們首先搭建如下架構: ShaderBase:繪制shader。GeometryGenerator:幾何體結構。LightHelper:描述光照。BoxShader:我們demo的著色器實現。BoxDemo:我們最終展示的demo。 我們先實現以上部分功能。 1.ShderBase 我們只定義頂點著色器與像素/片元著色器(自己實現這兩個都差不多,下文統一稱呼為像素著色器)的基本實現。 ShaderBase.h #pragma once #include "Vertex.h" #include "MVector.h" #include "MMath.h" #include "LightHelper.h" class ShaderBase { public: ShaderBase(); virtual ~ShaderBase(); public: virtual VertexOut VS(const VertexIn& vin) = 0; //頂點著色器 virtual MVector PS(VertexOut& pin) = 0; //像素著色器 }; ShaderBase.cpp #include "ShaderBase.h" ShaderBase::ShaderBase() { } ShaderBase::~ShaderBase() { } 2.1GeometryGenerator.h 我們定義幾何體結構,由頂點+索引組成,同時為該結構創建一個單例,并且創建一個立方體作為以后的demo。 #pragma once #include "MMath.h" class GeometryGenerator { private: GeometryGenerator() {} public: //單例模式 static GeometryGenerator* GetInstance() { static GeometryGenerator instance; return &instance; } //基本網絡結構:頂點集合+索引集合 struct MeshData { std::vector<VertexIn> vertices; std::vector<UINT> indices; }; //創建一個立方體:指定寬(X方向)、高(Y方向)、深(Z方向) void CreateBox(float width, float height, float depth, MeshData &mesh); }; 2.1GeometryGenerator.cpp 填入各個部分的頂點和索引信息。 #include "./GeometryGenerator.h" void GeometryGenerator::CreateBox(float width, float height, float depth, MeshData &mesh) { mesh.vertices.clear(); mesh.indices.clear(); //一共24個頂點(每面4個) mesh.vertices.resize(24); //一共36個索引(每面6個) mesh.indices.resize(36); float halfW = width * 0.5f; float halfH = height * 0.5f; float halfD = depth * 0.5f; //眼睛面向z軸正方向 //構建頂點 //前面 mesh.vertices[0].pos = MVector(-halfW, -halfH, -halfD,1.f); mesh.vertices[0].normal = MVector(0.f, 0.f, -1.f); mesh.vertices[0].color = MVector(1.f, 0.f, 0.f,1.f); mesh.vertices[0].tex = MFLOAT2(0.f, 1.f); mesh.vertices[1].pos = MVector(-halfW, halfH, -halfD,1.f); mesh.vertices[1].normal = MVector(0.f, 0.f, -1.f); mesh.vertices[1].color = MVector(0.f, 0.f, 0.f, 1.f); mesh.vertices[1].tex = MFLOAT2(0.f, 0.f); mesh.vertices[2].pos = MVector(halfW, halfH, -halfD, 1.f); mesh.vertices[2].normal = MVector(0.f, 0.f, -1.f); mesh.vertices[2].color = MVector(1.f, 0.f, 0.f, 1.f); mesh.vertices[2].tex = MFLOAT2(1.f, 0.f); mesh.vertices[3].pos = MVector(halfW, -halfH, -halfD, 1.f); mesh.vertices[3].normal = MVector(0.f, 0.f, -1.f); mesh.vertices[3].color = MVector(0.f, 1.f, 0.f, 1.f); mesh.vertices[3].tex = MFLOAT2(1.f, 1.f); //省略其他面 ...... } 3.1LightHelper.h: 描述光照,包含點光源,平行光,聚光燈以及材質。內容很簡單,自己看注釋吧。 注意 //入射光線關于法線的反射向量 MVector v = MathUtil::Reflect(-lightVec, normal); float specFactor = pow(max(v.Dot(toEye), 0.0f), mat.specular.w); //計算漫反射光 diffuse = mat.diffuse * L.diffuse * diffuseFactor; //計算高光 spec = mat.specular * L.specular * specFactor; #pragma once #include <windows.h> #include <algorithm> #include "../Math/MMath.h" namespace Lights { //平行光 struct DirectionalLight { DirectionalLight() { ZeroMemory(this, sizeof(this)); } MVector ambient; //環境光 MVector diffuse; //漫反射光 MVector specular; //高光 MVector direction; //光照方向 }; //點光源 struct PointLight { PointLight() { ZeroMemory(this, sizeof(this)); } MVector ambient; MVector diffuse; MVector specular; MVector position;//光源位置 MVector att; //衰減系數 float range; //光照范圍 }; //聚光燈 struct SpotLight { SpotLight() { ZeroMemory(this, sizeof(this)); } MVector ambient; MVector diffuse; MVector specular; MVector position; //光照位置 MVector direction; //光照方向 MVector att; //衰減系數 float range; //光照范圍 float spot; //光照強度系數 }; //材質 struct Material { Material() { ZeroMemory(this, sizeof(this)); } MVector ambient; MVector diffuse; MVector specular;//w表示高光強度 MVector reflect; }; //計算平行光 inline void ComputeDirectionalLight( const Material& mat, //材質 const DirectionalLight& L, //平行光 MVector normal, //頂點法線 MVector toEye, //頂點到眼睛的向量 MVector & ambient, //計算結果:環境光 MVector & diffuse, //計算結果:漫反射光 MVector & spec) //計算結果:高光 { // 結果初始化為0 ambient = MVector( 0.0f, 0.0f, 0.0f, 0.0f ); diffuse = MVector(0.0f, 0.0f, 0.0f, 0.0f); spec = MVector(0.0f, 0.0f, 0.0f, 0.0f); // 光線方向 MVector lightVec = -L.direction; // 環境光直接計算 ambient = mat.ambient * L.ambient; // 計算漫反射系數 //光線、法線方向歸一化 lightVec.Normalize(); float diffuseFactor = lightVec.Dot(normal); // 頂點背向光源不再計算 if (diffuseFactor > 0.0f) { //入射光線關于法線的反射向量 MVector v = MathUtil::Reflect(-lightVec, normal); float specFactor = pow(max(v.Dot(toEye), 0.0f), mat.specular.w); //計算漫反射光 diffuse = mat.diffuse * L.diffuse * diffuseFactor; //計算高光 spec = mat.specular * L.specular * specFactor; } } //計算點光源 inline void ComputePointLight( const Material& mat, //材質 PointLight L, //點光源 MVector pos, //頂點位置 MVector normal, //頂點法線 MVector toEye, //頂點到眼睛的向量 MVector& ambient, //計算結果:環境光 MVector& diffuse, //計算結果:漫反射光 MVector& spec) //計算結果:高光 { ambient = MVector(0.0f, 0.0f, 0.0f, 0.0f); diffuse = MVector(0.0f, 0.0f, 0.0f, 0.0f); spec = MVector(0.0f, 0.0f, 0.0f, 0.0f); //光照方向:頂點到光源 MVector lightVec = L.position - pos; //頂點到光源距離 float d = MathUtil::Length(lightVec); //超過范圍不再計算 if (d > L.range) return; //歸一化光照方向 lightVec = lightVec * (1.f / d); //計算環境光 ambient = mat.ambient * L.ambient; //漫反射系數 float diffuseFactor = lightVec.Dot(normal); if (diffuseFactor > 0.0f) { MVector v = MathUtil::Reflect(-lightVec, normal); float specFactor = pow(max(v.Dot(toEye), 0.0f), mat.specular.w); //計算漫反射光 diffuse = mat.diffuse * L.diffuse * diffuseFactor; //計算高光 spec = mat.specular * L.specular * specFactor; } // 計算衰減 float att = 1.f / L.att.Dot(MVector(1.f, d, d*d)); diffuse = diffuse * att; spec = diffuse * att; } //計算聚光燈 inline void ComputeSpotLight( const Material& mat, //材質 const SpotLight& L, //聚光燈 MVector pos, //頂點位置 MVector normal, //頂點法線 MVector toEye, //頂點到眼睛向量 MVector& ambient, //計算結果:環境光 MVector& diffuse, //計算結果:漫反射光 MVector& spec) //計算結果:高光 { //初始化結果 ambient = MVector(0.0f, 0.0f, 0.0f, 0.0f); diffuse = MVector(0.0f, 0.0f, 0.0f, 0.0f); spec = MVector(0.0f, 0.0f, 0.0f, 0.0f); //光照方向:頂點到光源 MVector lightVec = L.position - pos; //頂點到光源距離 float d = MathUtil::Length(lightVec); //距離大于光照方向不再計算 if (d > L.range) return; //歸一化光照方向 lightVec = lightVec * (1.f / d); //計算環境光 ambient = mat.ambient * L.ambient; //計算漫反射系數 float diffuseFactor = lightVec.Dot(normal); if (diffuseFactor > 0.0f) { MVector v = MathUtil::Reflect(-lightVec, normal); float specFactor = pow(max(v.Dot(toEye), 0.0f), mat.specular.w); //漫反射光 diffuse = mat.diffuse * L.diffuse * diffuseFactor; //高光 spec = mat.specular * L.specular * specFactor; } //聚光衰減系數 float spot = pow(max(-lightVec.Dot(L.direction), 0.0f), L.spot); //衰減系數 float att = spot / L.att.Dot(MVector(1.0f, d, d*d)); ambient = ambient * spot; diffuse = diffuse * att; spec = spec * att; } } 4.1BoxShader.h: 定義下我們demo的著色器實現。 把我們的box實現model->world->view->clip->screen。 #pragma once #include "ShaderBase.h" #include "MMath.h" class BoxShader : public ShaderBase { public: BoxShader(); ~BoxShader(); private: MMatrix m_worldViewProj; //世界視角投影矩陣 Texture2D m_tex; //紋理 MMatrix m_world; //世界矩陣 MMatrix m_worldInvTranspose; //世界矩陣逆矩陣的轉置,用于調整法線 Lights::Material m_material; //材質 Lights::DirectionalLight m_dirLight; //平行光 MVector m_eyePos; //觀察點 public: void SetWorldViewProj(const MMatrix& worldViewProj); void SetTexture(const Texture2D& tex); void SetWorld(const MMatrix& world); void SetWorldInvTranspose(const MMatrix& worldInvTrans); void SetEyePos(const MVector& eyePos); void SetMaterial(const Lights::Material& material); void SetDirLight(const Lights::DirectionalLight& dirLight); public: VertexOut VS(const VertexIn& vin); //頂點著色器 MVector PS(VertexOut& pin); }; 4.2BoxShader.cpp 重點只在于 //紋理+光照計算公式: 紋理*(環境光+漫反射光)+高光 MVector litColor = texColor * (ambient + diffuse) + specular; //最終顏色透明度使用漫反射光的透明度 litColor.w = m_material.diffuse.w * texColor.w; #include "BoxShader.h" BoxShader::BoxShader() { } BoxShader::~BoxShader() { } void BoxShader::SetWorldViewProj(const MMatrix& worldViewProj) { m_worldViewProj = worldViewProj; } void BoxShader::SetTexture(const Texture2D& tex) { m_tex = tex; } void BoxShader::SetWorld(const MMatrix& world) { m_world = world; } void BoxShader::SetWorldInvTranspose(const MMatrix& worldInvTrans) { m_worldInvTranspose = worldInvTrans; } void BoxShader::SetEyePos(const MVector& eyePos) { m_eyePos = eyePos; } void BoxShader::SetMaterial(const Lights::Material& material) { m_material.ambient = material.ambient; m_material.diffuse = material.diffuse; m_material.reflect = material.reflect; m_material.specular = material.specular; } void BoxShader::SetDirLight(const Lights::DirectionalLight& dirLight) { m_dirLight.ambient = dirLight.ambient; m_dirLight.diffuse = dirLight.diffuse; m_dirLight.direction = dirLight.direction; m_dirLight.specular = dirLight.specular; } VertexOut BoxShader::VS(const VertexIn& vin) { VertexOut out; out.posH = vin.pos * m_worldViewProj; out.posTrans = vin.pos * m_world; out.normal = out.normal * m_worldInvTranspose; out.color = vin.color; out.tex = vin.tex; return out; } MVector BoxShader::PS(VertexOut& pin) { //單位化法線 pin.normal.Normalize(); //紋理采樣 MVector texColor = m_tex.Sample(pin.tex); //頂點到觀察點向量 MVector toEye = (m_eyePos - pin.posTrans).Normalize(); //初始化顏色值全部為0 MVector ambient(0.f, 0.f, 0.f, 0.f); MVector diffuse(0.f, 0.f, 0.f, 0.f); MVector specular(0.f, 0.f, 0.f, 0.f); //光源計算后得到的環境光、漫反射 、高光 MVector A, D, S; Lights::ComputeDirectionalLight(m_material, m_dirLight, pin.normal, toEye, A, D, S); ambient = ambient + A; diffuse = diffuse + D; specular = specular + S; //紋理+光照計算公式: 紋理*(環境光+漫反射光)+高光 MVector litColor = texColor * (ambient + diffuse) + specular; //最終顏色透明度使用漫反射光的透明度 litColor.w = m_material.diffuse.w * texColor.w; return litColor; } 5.1BoxDemo.h 我們定義出自己demo各部分所需要的數據結構,包括各種矩陣的運算,頂點、材質、紋理、光照等。 #pragma once #include "Moe3D.h" #include "BoxShader.h" #include "MMath.h" #include "GeometryGenerator.h" class BoxDemo { public: BoxDemo(); ~BoxDemo(); public: bool Init(HINSTANCE hInstance, HWND hWnd); void Update(float dt); void Render(); void Clear(); //鼠標事件控制 void OnMouseDown(WPARAM btnState, int x, int y); void OnMouseUp(WPARAM btnState, int x, int y); void OnMouseMove(WPARAM btnState, int x, int y); public: inline Moe3DDevice*& GetDevice() { return m_pDevice; } private: int m_width, m_height; HINSTANCE m_hInstance; HWND m_hWnd; Moe3DDevice* m_pDevice; Moe3DDeviceContext* m_pImmediateContext; BoxShader* m_pShader; MMatrix m_worldViewProj; //世界視角投影矩陣 MMatrix m_world; //世界變換矩陣 MMatrix m_worldInvTranspose; //世界變換逆矩陣的轉置 用于調整法線 std::vector<VertexIn> m_vertices; //頂點緩沖 std::vector<UINT> m_indices; //索引緩沖 GeometryGenerator::MeshData m_box; Texture2D m_tex; //紋理 Lights::Material m_material; //材質 Lights::DirectionalLight m_dirLight; //平行光源 //控制攝像機位置角度等 float m_theta; float m_phi; float m_radius; POINT m_lastMousePos; }; 經過以上的過程,我們自己搭建了一套數學庫,然后自己實現了圖片的讀取,這次我們又完善了光照的參數,以及模型空間-世界空間-視角空間-裁剪空間-屏幕空間的轉換。并且搭建了我們的Billiard框架,即一個正方體的各部分的信息結構,如頂點+索引+貼圖+材質等。 這節就到這,下次再把整個案例完成。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看