add static and animation PBR shader, improve [camera renderer material] class
This commit is contained in:
@ -36,6 +36,7 @@ namespace Prism
|
|||||||
PushOverlay(m_ImGuiLayer);
|
PushOverlay(m_ImGuiLayer);
|
||||||
|
|
||||||
Renderer::Init();
|
Renderer::Init();
|
||||||
|
Renderer::Get().WaitAndRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application()
|
Application::~Application()
|
||||||
|
|||||||
@ -63,6 +63,12 @@ namespace Prism
|
|||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
using Ref = std::shared_ptr<T>;
|
using Ref = std::shared_ptr<T>;
|
||||||
|
|
||||||
|
template<typename T, typename ... Args>
|
||||||
|
constexpr Ref<T> CreateRef(Args&& ... args)
|
||||||
|
{
|
||||||
|
return std::make_shared<T>(std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif //CORE_H
|
#endif //CORE_H
|
||||||
|
|||||||
@ -38,6 +38,7 @@ namespace Prism
|
|||||||
virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
|
virtual void SetEventCallback(const EventCallbackFn& callback) = 0;
|
||||||
virtual unsigned int GetWidth() const = 0;
|
virtual unsigned int GetWidth() const = 0;
|
||||||
virtual unsigned int GetHeight() const = 0;
|
virtual unsigned int GetHeight() const = 0;
|
||||||
|
virtual std::pair<float, float> GetWindowPos() const = 0;
|
||||||
|
|
||||||
virtual void SetVSync(bool enable) = 0;
|
virtual void SetVSync(bool enable) = 0;
|
||||||
virtual bool const IsVSync() const = 0;
|
virtual bool const IsVSync() const = 0;
|
||||||
|
|||||||
@ -11,9 +11,11 @@
|
|||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
OpenGLFrameBuffer::OpenGLFrameBuffer(const uint32_t width, const uint32_t height, const FramebufferFormat format)
|
OpenGLFrameBuffer::OpenGLFrameBuffer(const uint32_t width, const uint32_t height, const FramebufferFormat format)
|
||||||
: m_Width(width), m_Height(height), m_Format(format)
|
: m_Format(format)
|
||||||
{
|
{
|
||||||
Resize(width, height);
|
OpenGLFrameBuffer::Resize(width, height);
|
||||||
|
m_Width = width;
|
||||||
|
m_Height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenGLFrameBuffer::~OpenGLFrameBuffer()
|
OpenGLFrameBuffer::~OpenGLFrameBuffer()
|
||||||
|
|||||||
@ -31,7 +31,7 @@ namespace Prism
|
|||||||
virtual FramebufferFormat GetFormat() const { return m_Format; }
|
virtual FramebufferFormat GetFormat() const { return m_Format; }
|
||||||
private:
|
private:
|
||||||
RendererID m_RendererID = 0;
|
RendererID m_RendererID = 0;
|
||||||
uint32_t m_Width, m_Height;
|
uint32_t m_Width = 0, m_Height = 0;
|
||||||
FramebufferFormat m_Format;
|
FramebufferFormat m_Format;
|
||||||
|
|
||||||
RendererID m_ColorAttachment, m_DepthAttachment;
|
RendererID m_ColorAttachment, m_DepthAttachment;
|
||||||
|
|||||||
@ -27,6 +27,7 @@ namespace Prism
|
|||||||
void RendererAPI::Init()
|
void RendererAPI::Init()
|
||||||
{
|
{
|
||||||
glDebugMessageCallback(OpenGLLogMessage, nullptr);
|
glDebugMessageCallback(OpenGLLogMessage, nullptr);
|
||||||
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
|
|
||||||
unsigned int vao;
|
unsigned int vao;
|
||||||
|
|||||||
@ -12,8 +12,12 @@ namespace Prism
|
|||||||
OpenGLShader::OpenGLShader(const std::string& filepath)
|
OpenGLShader::OpenGLShader(const std::string& filepath)
|
||||||
: m_AssetPath(filepath)
|
: m_AssetPath(filepath)
|
||||||
{
|
{
|
||||||
const size_t found = filepath.find_last_of("/\\");
|
size_t found = filepath.find_last_of("/\\");
|
||||||
m_Name = found != std::string::npos ? filepath.substr(found + 1) : filepath;
|
m_Name = found != std::string::npos ? filepath.substr(found + 1) : filepath;
|
||||||
|
|
||||||
|
found = m_Name.find_last_of('.');
|
||||||
|
m_Name = found != std::string::npos ? m_Name.substr(0, found) : m_Name;
|
||||||
|
|
||||||
OpenGLShader::Reload();
|
OpenGLShader::Reload();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -83,7 +83,7 @@ namespace Prism
|
|||||||
inline const ShaderUniformBufferDeclaration& GetPSMaterialUniformBuffer() const override { return *m_PSMaterialUniformBuffer; }
|
inline const ShaderUniformBufferDeclaration& GetPSMaterialUniformBuffer() const override { return *m_PSMaterialUniformBuffer; }
|
||||||
inline const ShaderResourceList& GetResources() const override { return m_Resources; }
|
inline const ShaderResourceList& GetResources() const override { return m_Resources; }
|
||||||
private:
|
private:
|
||||||
RendererID m_RendererID;
|
RendererID m_RendererID = 0;
|
||||||
|
|
||||||
bool m_Loaded = false;
|
bool m_Loaded = false;
|
||||||
|
|
||||||
|
|||||||
@ -58,6 +58,13 @@ namespace Prism
|
|||||||
m_Data.VSync = enable;
|
m_Data.VSync = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<float, float> WindowsWindow::GetWindowPos() const
|
||||||
|
{
|
||||||
|
int x, y;
|
||||||
|
glfwGetWindowPos(m_Window, &x, &y);
|
||||||
|
return { x, y };
|
||||||
|
}
|
||||||
|
|
||||||
void WindowsWindow::Init(const WindowProps& props)
|
void WindowsWindow::Init(const WindowProps& props)
|
||||||
{
|
{
|
||||||
m_Data.Title = props.Title;
|
m_Data.Title = props.Title;
|
||||||
|
|||||||
@ -24,6 +24,7 @@ namespace Prism
|
|||||||
inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
|
inline void SetEventCallback(const EventCallbackFn& callback) override { m_Data.EventCallback = callback; }
|
||||||
bool const IsVSync() const override { return m_Data.VSync; }
|
bool const IsVSync() const override { return m_Data.VSync; }
|
||||||
void SetVSync(bool enable) override;
|
void SetVSync(bool enable) override;
|
||||||
|
virtual std::pair<float, float> GetWindowPos() const override;
|
||||||
|
|
||||||
inline void* GetNativeWindow() const { return m_Window; }
|
inline void* GetNativeWindow() const { return m_Window; }
|
||||||
|
|
||||||
|
|||||||
@ -14,7 +14,7 @@ namespace Prism
|
|||||||
public:
|
public:
|
||||||
virtual ~VertexBuffer() {}
|
virtual ~VertexBuffer() {}
|
||||||
|
|
||||||
virtual void SetData(void* buffer, unsigned int size, unsigned int offset = 0) = 0;
|
virtual void SetData(void* buffer, uint32_t size, uint32_t offset = 0) = 0;
|
||||||
virtual void Bind() const = 0;
|
virtual void Bind() const = 0;
|
||||||
|
|
||||||
virtual unsigned int GetSize() const = 0;
|
virtual unsigned int GetSize() const = 0;
|
||||||
|
|||||||
@ -22,11 +22,6 @@ namespace Prism
|
|||||||
Camera::Camera(const glm::mat4& projectionMatrix)
|
Camera::Camera(const glm::mat4& projectionMatrix)
|
||||||
: m_ProjectionMatrix(projectionMatrix)
|
: m_ProjectionMatrix(projectionMatrix)
|
||||||
{
|
{
|
||||||
// Sensible defaults
|
|
||||||
m_PanSpeed = 0.15f;
|
|
||||||
m_RotationSpeed = 0.5f;
|
|
||||||
m_ZoomSpeed = 10.0f;
|
|
||||||
|
|
||||||
m_Position = { 0, 0, 10 };
|
m_Position = { 0, 0, 10 };
|
||||||
m_Rotation = glm::vec3(90.0f, 0.0f, 0.0f);
|
m_Rotation = glm::vec3(90.0f, 0.0f, 0.0f);
|
||||||
|
|
||||||
@ -85,23 +80,25 @@ namespace Prism
|
|||||||
|
|
||||||
void Camera::MousePan(const glm::vec2& delta)
|
void Camera::MousePan(const glm::vec2& delta)
|
||||||
{
|
{
|
||||||
m_FocalPoint += -GetRightDirection() * delta.x * m_PanSpeed * m_Distance;
|
auto [xSpeed, ySpeed] = PanSpeed();
|
||||||
m_FocalPoint += GetUpDirection() * delta.y * m_PanSpeed * m_Distance;
|
// PM_CORE_TRACE("{0}, {1}", xSpeed, ySpeed);
|
||||||
|
m_FocalPoint += -GetRightDirection() * delta.x * xSpeed * m_Distance;
|
||||||
|
m_FocalPoint += GetUpDirection() * delta.y * ySpeed * m_Distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::MouseRotate(const glm::vec2& delta)
|
void Camera::MouseRotate(const glm::vec2& delta)
|
||||||
{
|
{
|
||||||
float yawSign = GetUpDirection().y < 0 ? -1.0f : 1.0f;
|
float yawSign = GetUpDirection().y < 0 ? -1.0f : 1.0f;
|
||||||
m_Yaw += yawSign * delta.x * m_RotationSpeed;
|
m_Yaw += yawSign * delta.x * RotationSpeed();
|
||||||
m_Pitch += delta.y * m_RotationSpeed;
|
m_Pitch += delta.y * RotationSpeed();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Camera::MouseZoom(float delta)
|
void Camera::MouseZoom(const float delta)
|
||||||
{
|
{
|
||||||
m_Distance -= delta * m_ZoomSpeed;
|
m_Distance -= delta * ZoomSpeed();
|
||||||
if (m_Distance < 1.0f)
|
if (m_Distance < 1.0f)
|
||||||
{
|
{
|
||||||
m_FocalPoint += GetForwardDirection();
|
m_FocalPoint += GetForwardDirection() * delta;
|
||||||
m_Distance = 1.0f;
|
m_Distance = 1.0f;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -115,4 +112,29 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
return glm::quat(glm::vec3(-m_Pitch, -m_Yaw, 0.0f));
|
return glm::quat(glm::vec3(-m_Pitch, -m_Yaw, 0.0f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::pair<float, float> Camera::PanSpeed() const
|
||||||
|
{
|
||||||
|
const float x = std::min(m_ViewportWidth / 1000.0f, 2.4f); // max = 2.4f
|
||||||
|
float xFactor = 0.0366f * (x * x) - 0.1778f * x + 0.3021f;
|
||||||
|
|
||||||
|
const float y = std::min(m_ViewportHeight / 1000.0f, 2.4f); // max = 2.4f
|
||||||
|
float yFactor = 0.0366f * (y * y) - 0.1778f * y + 0.3021f;
|
||||||
|
|
||||||
|
return { xFactor, yFactor };
|
||||||
|
}
|
||||||
|
|
||||||
|
float Camera::RotationSpeed() const
|
||||||
|
{
|
||||||
|
return 0.8f;
|
||||||
|
}
|
||||||
|
|
||||||
|
float Camera::ZoomSpeed() const
|
||||||
|
{
|
||||||
|
float distance = m_Distance * 0.2f;
|
||||||
|
distance = std::max(distance, 0.0f);
|
||||||
|
float speed = distance * distance;
|
||||||
|
speed = std::min(speed, 100.0f); // max speed = 100
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,6 +32,8 @@ namespace Prism
|
|||||||
glm::vec3 GetRightDirection();
|
glm::vec3 GetRightDirection();
|
||||||
glm::vec3 GetForwardDirection();
|
glm::vec3 GetForwardDirection();
|
||||||
const glm::vec3& GetPosition() const { return m_Position; }
|
const glm::vec3& GetPosition() const { return m_Position; }
|
||||||
|
public:
|
||||||
|
inline void SetViewportSize(const uint32_t width, const uint32_t height) { m_ViewportWidth = width; m_ViewportHeight = height; }
|
||||||
private:
|
private:
|
||||||
void MousePan(const glm::vec2& delta);
|
void MousePan(const glm::vec2& delta);
|
||||||
void MouseRotate(const glm::vec2& delta);
|
void MouseRotate(const glm::vec2& delta);
|
||||||
@ -39,6 +41,10 @@ namespace Prism
|
|||||||
|
|
||||||
glm::vec3 CalculatePosition();
|
glm::vec3 CalculatePosition();
|
||||||
glm::quat GetOrientation();
|
glm::quat GetOrientation();
|
||||||
|
|
||||||
|
std::pair<float, float> PanSpeed() const;
|
||||||
|
float RotationSpeed() const;
|
||||||
|
float ZoomSpeed() const;
|
||||||
private:
|
private:
|
||||||
glm::mat4 m_ProjectionMatrix, m_ViewMatrix;
|
glm::mat4 m_ProjectionMatrix, m_ViewMatrix;
|
||||||
glm::vec3 m_Position, m_Rotation, m_FocalPoint;
|
glm::vec3 m_Position, m_Rotation, m_FocalPoint;
|
||||||
@ -47,8 +53,9 @@ namespace Prism
|
|||||||
glm::vec2 m_InitialMousePosition;
|
glm::vec2 m_InitialMousePosition;
|
||||||
glm::vec3 m_InitialFocalPoint, m_InitialRotation;
|
glm::vec3 m_InitialFocalPoint, m_InitialRotation;
|
||||||
|
|
||||||
|
uint32_t m_ViewportWidth = 1280, m_ViewportHeight = 720;
|
||||||
|
|
||||||
float m_Distance;
|
float m_Distance;
|
||||||
float m_PanSpeed, m_RotationSpeed, m_ZoomSpeed;
|
|
||||||
|
|
||||||
float m_Pitch, m_Yaw;
|
float m_Pitch, m_Yaw;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -17,6 +17,10 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<Material> Material::Create(const Ref<Shader>& shader)
|
||||||
|
{
|
||||||
|
return CreateRef<Material>(shader);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Material::AllocateStorage()
|
void Material::AllocateStorage()
|
||||||
@ -120,6 +124,11 @@ namespace Prism
|
|||||||
m_Material->m_MaterialInstances.erase(this);
|
m_Material->m_MaterialInstances.erase(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ref<MaterialInstance> MaterialInstance::Create(const Ref<Material>& material)
|
||||||
|
{
|
||||||
|
return CreateRef<MaterialInstance>(material);
|
||||||
|
}
|
||||||
|
|
||||||
void MaterialInstance::OnShaderReloaded()
|
void MaterialInstance::OnShaderReloaded()
|
||||||
{
|
{
|
||||||
AllocateStorage();
|
AllocateStorage();
|
||||||
|
|||||||
@ -23,6 +23,8 @@ namespace Prism
|
|||||||
Material(const Ref<Shader>& shader);
|
Material(const Ref<Shader>& shader);
|
||||||
virtual ~Material();
|
virtual ~Material();
|
||||||
|
|
||||||
|
static Ref<Material> Create(const Ref<Shader>& shader);
|
||||||
|
|
||||||
void Bind() const;
|
void Bind() const;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -31,7 +33,8 @@ namespace Prism
|
|||||||
|
|
||||||
void Set(const std::string& name, const Ref<Texture>& texture)
|
void Set(const std::string& name, const Ref<Texture>& texture)
|
||||||
{
|
{
|
||||||
auto decl = FindResourceDeclaration(name);
|
const auto decl = FindResourceDeclaration(name);
|
||||||
|
if (!decl) return;
|
||||||
uint32_t slot = decl->GetRegister();
|
uint32_t slot = decl->GetRegister();
|
||||||
if (m_Textures.size() <= slot)
|
if (m_Textures.size() <= slot)
|
||||||
m_Textures.resize((size_t)slot + 1);
|
m_Textures.resize((size_t)slot + 1);
|
||||||
@ -55,6 +58,7 @@ namespace Prism
|
|||||||
ShaderUniformDeclaration* FindUniformDeclaration(const std::string& name);
|
ShaderUniformDeclaration* FindUniformDeclaration(const std::string& name);
|
||||||
ShaderResourceDeclaration* FindResourceDeclaration(const std::string& name);
|
ShaderResourceDeclaration* FindResourceDeclaration(const std::string& name);
|
||||||
Buffer& GetUniformBufferTarget(ShaderUniformDeclaration* uniformDeclaration);
|
Buffer& GetUniformBufferTarget(ShaderUniformDeclaration* uniformDeclaration);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ref<Shader> m_Shader;
|
Ref<Shader> m_Shader;
|
||||||
std::unordered_set<MaterialInstance*> m_MaterialInstances;
|
std::unordered_set<MaterialInstance*> m_MaterialInstances;
|
||||||
@ -75,6 +79,8 @@ namespace Prism
|
|||||||
MaterialInstance(const Ref<Material>& material);
|
MaterialInstance(const Ref<Material>& material);
|
||||||
virtual ~MaterialInstance();
|
virtual ~MaterialInstance();
|
||||||
|
|
||||||
|
static Ref<MaterialInstance> Create(const Ref<Material>& material);
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void Set(const std::string& name, const T& value)
|
void Set(const std::string& name, const T& value)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -57,7 +57,7 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Vertex::AddBoneData(uint32_t BoneID, float Weight)
|
void AnimatedVertex::AddBoneData(uint32_t BoneID, float Weight)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < 4; i++)
|
for (size_t i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
@ -103,6 +103,9 @@ namespace Prism
|
|||||||
PM_CORE_ERROR("Failed to load mesh file: {0}", filename);
|
PM_CORE_ERROR("Failed to load mesh file: {0}", filename);
|
||||||
|
|
||||||
|
|
||||||
|
m_IsAnimated = scene->mAnimations != nullptr;
|
||||||
|
m_MeshShader = m_IsAnimated ? Renderer::GetShaderLibrary()->Get("simplepbr_Anim") : Renderer::GetShaderLibrary()->Get("simplepbr_Static");
|
||||||
|
m_Material.reset(new Prism::Material(m_MeshShader));
|
||||||
m_InverseTransform = glm::inverse(aiMatrix4x4ToGlm(scene->mRootNode->mTransformation));
|
m_InverseTransform = glm::inverse(aiMatrix4x4ToGlm(scene->mRootNode->mTransformation));
|
||||||
|
|
||||||
uint32_t vertexCount = 0;
|
uint32_t vertexCount = 0;
|
||||||
@ -127,6 +130,26 @@ namespace Prism
|
|||||||
PM_CORE_ASSERT(mesh->HasNormals(), "Meshes require normals.");
|
PM_CORE_ASSERT(mesh->HasNormals(), "Meshes require normals.");
|
||||||
|
|
||||||
// Vertices
|
// Vertices
|
||||||
|
if (m_IsAnimated)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < mesh->mNumVertices; i++)
|
||||||
|
{
|
||||||
|
AnimatedVertex vertex;
|
||||||
|
vertex.Position = { mesh->mVertices[i].x, mesh->mVertices[i].y, mesh->mVertices[i].z };
|
||||||
|
vertex.Normal = { mesh->mNormals[i].x, mesh->mNormals[i].y, mesh->mNormals[i].z };
|
||||||
|
|
||||||
|
if (mesh->HasTangentsAndBitangents())
|
||||||
|
{
|
||||||
|
vertex.Tangent = { mesh->mTangents[i].x, mesh->mTangents[i].y, mesh->mTangents[i].z };
|
||||||
|
vertex.Binormal = { mesh->mBitangents[i].x, mesh->mBitangents[i].y, mesh->mBitangents[i].z };
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh->HasTextureCoords(0))
|
||||||
|
vertex.Texcoord = { mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y };
|
||||||
|
m_AnimatedVertices.push_back(vertex);
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
{
|
||||||
for (size_t i = 0; i < mesh->mNumVertices; i++)
|
for (size_t i = 0; i < mesh->mNumVertices; i++)
|
||||||
{
|
{
|
||||||
Vertex vertex;
|
Vertex vertex;
|
||||||
@ -141,7 +164,9 @@ namespace Prism
|
|||||||
|
|
||||||
if (mesh->HasTextureCoords(0))
|
if (mesh->HasTextureCoords(0))
|
||||||
vertex.Texcoord = { mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y };
|
vertex.Texcoord = { mesh->mTextureCoords[0][i].x, mesh->mTextureCoords[0][i].y };
|
||||||
m_Vertices.push_back(vertex);
|
|
||||||
|
m_StaticVertices.push_back(vertex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Indices
|
// Indices
|
||||||
@ -152,7 +177,15 @@ namespace Prism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PM_CORE_TRACE("NODES:");
|
||||||
|
PM_CORE_TRACE("-----------------------------");
|
||||||
|
TraverseNodes(scene->mRootNode);
|
||||||
|
PM_CORE_TRACE("-----------------------------");
|
||||||
|
|
||||||
// Bones
|
// Bones
|
||||||
|
if (m_IsAnimated)
|
||||||
|
{
|
||||||
for (size_t m = 0; m < scene->mNumMeshes; m++)
|
for (size_t m = 0; m < scene->mNumMeshes; m++)
|
||||||
{
|
{
|
||||||
aiMesh* mesh = scene->mMeshes[m];
|
aiMesh* mesh = scene->mMeshes[m];
|
||||||
@ -184,13 +217,17 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
int VertexID = submesh.BaseVertex + bone->mWeights[j].mVertexId;
|
int VertexID = submesh.BaseVertex + bone->mWeights[j].mVertexId;
|
||||||
float Weight = bone->mWeights[j].mWeight;
|
float Weight = bone->mWeights[j].mWeight;
|
||||||
m_Vertices[VertexID].AddBoneData(boneIndex, Weight);
|
m_AnimatedVertices[VertexID].AddBoneData(boneIndex, Weight);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_VertexBuffer.reset(VertexBuffer::Create());
|
m_VertexBuffer.reset(VertexBuffer::Create());
|
||||||
m_VertexBuffer->SetData(m_Vertices.data(), m_Vertices.size() * sizeof(Vertex));
|
if (m_IsAnimated)
|
||||||
|
m_VertexBuffer->SetData(m_AnimatedVertices.data(), m_AnimatedVertices.size() * sizeof(AnimatedVertex));
|
||||||
|
else
|
||||||
|
m_VertexBuffer->SetData(m_StaticVertices.data(), m_StaticVertices.size() * sizeof(Vertex));
|
||||||
|
|
||||||
m_IndexBuffer.reset(IndexBuffer::Create());
|
m_IndexBuffer.reset(IndexBuffer::Create());
|
||||||
m_IndexBuffer->SetData(m_Indices.data(), m_Indices.size() * sizeof(Index));
|
m_IndexBuffer->SetData(m_Indices.data(), m_Indices.size() * sizeof(Index));
|
||||||
@ -202,9 +239,16 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mesh::Render(TimeStep deltaTime, Shader* shader)
|
void Mesh::Render(TimeStep deltaTime, const Ref<MaterialInstance>& materialInstance)
|
||||||
{
|
{
|
||||||
if (m_AnimationPlaying && m_Scene->mAnimations)
|
Render(deltaTime, glm::mat4(1.0f), materialInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mesh::Render(TimeStep deltaTime, const glm::mat4& transform, const Ref<MaterialInstance>& materialInstance)
|
||||||
|
{
|
||||||
|
if (m_IsAnimated)
|
||||||
|
{
|
||||||
|
if (m_AnimationPlaying)
|
||||||
{
|
{
|
||||||
m_WorldTime += deltaTime;
|
m_WorldTime += deltaTime;
|
||||||
|
|
||||||
@ -213,16 +257,55 @@ namespace Prism
|
|||||||
m_AnimationTime = fmod(m_AnimationTime, (float)m_Scene->mAnimations[0]->mDuration);
|
m_AnimationTime = fmod(m_AnimationTime, (float)m_Scene->mAnimations[0]->mDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_Scene->mAnimations)
|
|
||||||
BoneTransform(m_AnimationTime);
|
BoneTransform(m_AnimationTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (materialInstance)
|
||||||
|
materialInstance->Bind();
|
||||||
|
|
||||||
// TODO: Sort this out
|
// TODO: Sort this out
|
||||||
m_VertexBuffer->Bind();
|
m_VertexBuffer->Bind();
|
||||||
m_IndexBuffer->Bind();
|
m_IndexBuffer->Bind();
|
||||||
|
|
||||||
|
bool materialOverride = !!materialInstance;
|
||||||
|
|
||||||
// TODO: replace with render API calls
|
// TODO: replace with render API calls
|
||||||
PM_RENDER_S1(shader, {
|
PM_RENDER_S2(transform, materialOverride,{
|
||||||
for (Submesh& submesh : self->m_Submeshes)
|
for (const Submesh& submesh : self->m_Submeshes)
|
||||||
|
{
|
||||||
|
if (self->m_IsAnimated)
|
||||||
|
{
|
||||||
|
glEnableVertexAttribArray(0);
|
||||||
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(AnimatedVertex), (const void*)offsetof(AnimatedVertex, Position));
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(1);
|
||||||
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(AnimatedVertex), (const void*)offsetof(AnimatedVertex, Normal));
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(2);
|
||||||
|
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, sizeof(AnimatedVertex), (const void*)offsetof(AnimatedVertex, Tangent));
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(3);
|
||||||
|
glVertexAttribPointer(3, 3, GL_FLOAT, GL_FALSE, sizeof(AnimatedVertex), (const void*)offsetof(AnimatedVertex, Binormal));
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(4);
|
||||||
|
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(AnimatedVertex), (const void*)offsetof(AnimatedVertex, Texcoord));
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(5);
|
||||||
|
glVertexAttribIPointer(5, 4, GL_INT, sizeof(AnimatedVertex), (const void*)offsetof(AnimatedVertex, IDs));
|
||||||
|
|
||||||
|
glEnableVertexAttribArray(6);
|
||||||
|
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(AnimatedVertex), (const void*)offsetof(AnimatedVertex, Weights));
|
||||||
|
|
||||||
|
if (self->m_Scene->mAnimations)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < self->m_BoneTransforms.size(); i++)
|
||||||
|
{
|
||||||
|
std::string uniformName = std::string("u_BoneTransforms[") + std::to_string(i) + std::string("]");
|
||||||
|
self->m_MeshShader->SetMat4FromRenderThread(uniformName, self->m_BoneTransforms[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||||
|
}else
|
||||||
{
|
{
|
||||||
glEnableVertexAttribArray(0);
|
glEnableVertexAttribArray(0);
|
||||||
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Position));
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Position));
|
||||||
@ -238,21 +321,9 @@ namespace Prism
|
|||||||
|
|
||||||
glEnableVertexAttribArray(4);
|
glEnableVertexAttribArray(4);
|
||||||
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Texcoord));
|
glVertexAttribPointer(4, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Texcoord));
|
||||||
|
|
||||||
glEnableVertexAttribArray(5);
|
|
||||||
glVertexAttribIPointer(5, 4, GL_INT, sizeof(Vertex), (const void*)offsetof(Vertex, IDs));
|
|
||||||
|
|
||||||
glEnableVertexAttribArray(6);
|
|
||||||
glVertexAttribPointer(6, 4, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const void*)offsetof(Vertex, Weights));
|
|
||||||
|
|
||||||
if (self->m_Scene->mAnimations)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < self->m_BoneTransforms.size(); i++)
|
|
||||||
{
|
|
||||||
std::string uniformName = std::string("u_BoneTransforms[") + std::to_string(i) + std::string("]");
|
|
||||||
shader->SetMat4FromRenderThread(uniformName, self->m_BoneTransforms[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (!materialOverride)
|
||||||
|
self->m_MeshShader->SetMat4FromRenderThread("u_ModelMatrix", transform * submesh.Transform);
|
||||||
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -262,6 +333,8 @@ namespace Prism
|
|||||||
{
|
{
|
||||||
ImGui::Begin("Mesh Debug");
|
ImGui::Begin("Mesh Debug");
|
||||||
if (ImGui::CollapsingHeader(m_FilePath.c_str()))
|
if (ImGui::CollapsingHeader(m_FilePath.c_str()))
|
||||||
|
{
|
||||||
|
if (m_IsAnimated)
|
||||||
{
|
{
|
||||||
if (ImGui::CollapsingHeader("Animation"))
|
if (ImGui::CollapsingHeader("Animation"))
|
||||||
{
|
{
|
||||||
@ -272,6 +345,7 @@ namespace Prism
|
|||||||
ImGui::DragFloat("Time Scale", &m_TimeMultiplier, 0.05f, 0.0f, 10.0f);
|
ImGui::DragFloat("Time Scale", &m_TimeMultiplier, 0.05f, 0.0f, 10.0f);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
}
|
}
|
||||||
@ -282,9 +356,11 @@ namespace Prism
|
|||||||
PM_CORE_TRACE("------------------------------------------------------");
|
PM_CORE_TRACE("------------------------------------------------------");
|
||||||
PM_CORE_TRACE("Vertex Buffer Dump");
|
PM_CORE_TRACE("Vertex Buffer Dump");
|
||||||
PM_CORE_TRACE("Mesh: {0}", m_FilePath);
|
PM_CORE_TRACE("Mesh: {0}", m_FilePath);
|
||||||
for (size_t i = 0; i < m_Vertices.size(); i++)
|
if (m_IsAnimated)
|
||||||
{
|
{
|
||||||
auto& vertex = m_Vertices[i];
|
for (size_t i = 0; i < m_AnimatedVertices.size(); i++)
|
||||||
|
{
|
||||||
|
auto& vertex = m_AnimatedVertices[i];
|
||||||
PM_CORE_TRACE("Vertex: {0}", i);
|
PM_CORE_TRACE("Vertex: {0}", i);
|
||||||
PM_CORE_TRACE("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z);
|
PM_CORE_TRACE("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z);
|
||||||
PM_CORE_TRACE("Normal: {0}, {1}, {2}", vertex.Normal.x, vertex.Normal.y, vertex.Normal.z);
|
PM_CORE_TRACE("Normal: {0}, {1}, {2}", vertex.Normal.x, vertex.Normal.y, vertex.Normal.z);
|
||||||
@ -293,6 +369,20 @@ namespace Prism
|
|||||||
PM_CORE_TRACE("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y);
|
PM_CORE_TRACE("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y);
|
||||||
PM_CORE_TRACE("--");
|
PM_CORE_TRACE("--");
|
||||||
}
|
}
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < m_StaticVertices.size(); i++)
|
||||||
|
{
|
||||||
|
auto& vertex = m_StaticVertices[i];
|
||||||
|
PM_CORE_TRACE("Vertex: {0}", i);
|
||||||
|
PM_CORE_TRACE("Position: {0}, {1}, {2}", vertex.Position.x, vertex.Position.y, vertex.Position.z);
|
||||||
|
PM_CORE_TRACE("Normal: {0}, {1}, {2}", vertex.Normal.x, vertex.Normal.y, vertex.Normal.z);
|
||||||
|
PM_CORE_TRACE("Binormal: {0}, {1}, {2}", vertex.Binormal.x, vertex.Binormal.y, vertex.Binormal.z);
|
||||||
|
PM_CORE_TRACE("Tangent: {0}, {1}, {2}", vertex.Tangent.x, vertex.Tangent.y, vertex.Tangent.z);
|
||||||
|
PM_CORE_TRACE("TexCoord: {0}, {1}", vertex.Texcoord.x, vertex.Texcoord.y);
|
||||||
|
PM_CORE_TRACE("--");
|
||||||
|
}
|
||||||
|
}
|
||||||
PM_CORE_TRACE("------------------------------------------------------");
|
PM_CORE_TRACE("------------------------------------------------------");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -337,6 +427,25 @@ namespace Prism
|
|||||||
ReadNodeHierarchy(AnimationTime, pNode->mChildren[i], transform);
|
ReadNodeHierarchy(AnimationTime, pNode->mChildren[i], transform);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Mesh::TraverseNodes(aiNode* node, int level)
|
||||||
|
{
|
||||||
|
std::string levelText;
|
||||||
|
for (int i = 0; i < level; i++)
|
||||||
|
levelText += "-";
|
||||||
|
PM_CORE_TRACE("{0}Node name: {1}", levelText, std::string(node->mName.data));
|
||||||
|
for (uint32_t i = 0; i < node->mNumMeshes; i++)
|
||||||
|
{
|
||||||
|
uint32_t mesh = node->mMeshes[i];
|
||||||
|
m_Submeshes[mesh].Transform = aiMatrix4x4ToGlm(node->mTransformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < node->mNumChildren; i++)
|
||||||
|
{
|
||||||
|
aiNode* child = node->mChildren[i];
|
||||||
|
TraverseNodes(child, level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const aiNodeAnim* Mesh::FindNodeAnim(const aiAnimation* animation, const std::string& nodeName)
|
const aiNodeAnim* Mesh::FindNodeAnim(const aiAnimation* animation, const std::string& nodeName)
|
||||||
{
|
{
|
||||||
for (uint32_t i = 0; i < animation->mNumChannels; i++)
|
for (uint32_t i = 0; i < animation->mNumChannels; i++)
|
||||||
|
|||||||
@ -8,6 +8,7 @@
|
|||||||
#include <glm/glm.hpp>
|
#include <glm/glm.hpp>
|
||||||
|
|
||||||
#include "Buffer.h"
|
#include "Buffer.h"
|
||||||
|
#include "Material.h"
|
||||||
#include "Shader.h"
|
#include "Shader.h"
|
||||||
#include "Prism/Core/TimeStep.h"
|
#include "Prism/Core/TimeStep.h"
|
||||||
|
|
||||||
@ -24,6 +25,15 @@ namespace Assimp
|
|||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
struct Vertex
|
struct Vertex
|
||||||
|
{
|
||||||
|
glm::vec3 Position;
|
||||||
|
glm::vec3 Normal;
|
||||||
|
glm::vec3 Tangent;
|
||||||
|
glm::vec3 Binormal;
|
||||||
|
glm::vec2 Texcoord;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct AnimatedVertex
|
||||||
{
|
{
|
||||||
glm::vec3 Position;
|
glm::vec3 Position;
|
||||||
glm::vec3 Normal;
|
glm::vec3 Normal;
|
||||||
@ -72,6 +82,8 @@ namespace Prism
|
|||||||
uint32_t BaseIndex;
|
uint32_t BaseIndex;
|
||||||
uint32_t MaterialIndex;
|
uint32_t MaterialIndex;
|
||||||
uint32_t IndexCount;
|
uint32_t IndexCount;
|
||||||
|
|
||||||
|
glm::mat4 Transform;
|
||||||
};
|
};
|
||||||
|
|
||||||
class PRISM_API Mesh
|
class PRISM_API Mesh
|
||||||
@ -82,14 +94,18 @@ namespace Prism
|
|||||||
Mesh(const std::string& filename);
|
Mesh(const std::string& filename);
|
||||||
~Mesh();
|
~Mesh();
|
||||||
|
|
||||||
void Render(TimeStep deltaTime, Shader* shader);
|
void Render(TimeStep deltaTime, const Ref<MaterialInstance>& materialInstance = Ref<MaterialInstance>());
|
||||||
|
void Render(TimeStep deltaTime, const glm::mat4& transform = glm::mat4(1.0f), const Ref<MaterialInstance>& materialInstance = Ref<MaterialInstance>());
|
||||||
void OnImGuiRender();
|
void OnImGuiRender();
|
||||||
void DumpVertexBuffer();
|
void DumpVertexBuffer();
|
||||||
|
|
||||||
|
inline Ref<Shader> GetMeshShader() { return m_MeshShader; }
|
||||||
|
inline Ref<Material> GetMaterial() { return m_Material; }
|
||||||
inline const std::string& GetFilePath() const { return m_FilePath; }
|
inline const std::string& GetFilePath() const { return m_FilePath; }
|
||||||
private:
|
private:
|
||||||
void BoneTransform(float time);
|
void BoneTransform(float time);
|
||||||
void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform);
|
void ReadNodeHierarchy(float AnimationTime, const aiNode* pNode, const glm::mat4& ParentTransform);
|
||||||
|
void TraverseNodes(aiNode* node, int level = 0);
|
||||||
|
|
||||||
const aiNodeAnim* FindNodeAnim(const aiAnimation* animation, const std::string& nodeName);
|
const aiNodeAnim* FindNodeAnim(const aiAnimation* animation, const std::string& nodeName);
|
||||||
uint32_t FindPosition(float AnimationTime, const aiNodeAnim* pNodeAnim);
|
uint32_t FindPosition(float AnimationTime, const aiNodeAnim* pNodeAnim);
|
||||||
@ -112,13 +128,20 @@ namespace Prism
|
|||||||
std::unique_ptr<VertexBuffer> m_VertexBuffer;
|
std::unique_ptr<VertexBuffer> m_VertexBuffer;
|
||||||
std::unique_ptr<IndexBuffer> m_IndexBuffer;
|
std::unique_ptr<IndexBuffer> m_IndexBuffer;
|
||||||
|
|
||||||
std::vector<Vertex> m_Vertices;
|
|
||||||
|
std::vector<Vertex> m_StaticVertices;
|
||||||
|
std::vector<AnimatedVertex> m_AnimatedVertices;
|
||||||
std::vector<Index> m_Indices;
|
std::vector<Index> m_Indices;
|
||||||
std::unordered_map<std::string, uint32_t> m_BoneMapping;
|
std::unordered_map<std::string, uint32_t> m_BoneMapping;
|
||||||
std::vector<glm::mat4> m_BoneTransforms;
|
std::vector<glm::mat4> m_BoneTransforms;
|
||||||
const aiScene* m_Scene;
|
const aiScene* m_Scene;
|
||||||
|
|
||||||
|
// Material
|
||||||
|
Ref<Shader> m_MeshShader;
|
||||||
|
Ref<Material> m_Material;
|
||||||
|
|
||||||
// Animation
|
// Animation
|
||||||
|
bool m_IsAnimated = false;
|
||||||
float m_AnimationTime = 0.0f;
|
float m_AnimationTime = 0.0f;
|
||||||
float m_WorldTime = 0.0f;
|
float m_WorldTime = 0.0f;
|
||||||
float m_TimeMultiplier = 1.0f;
|
float m_TimeMultiplier = 1.0f;
|
||||||
|
|||||||
@ -41,7 +41,11 @@ namespace Prism
|
|||||||
|
|
||||||
void Renderer::Init()
|
void Renderer::Init()
|
||||||
{
|
{
|
||||||
|
s_Instance->m_ShaderLibrary = std::make_unique<ShaderLibrary>();
|
||||||
PM_RENDER({ RendererAPI::Init(); });
|
PM_RENDER({ RendererAPI::Init(); });
|
||||||
|
|
||||||
|
GetShaderLibrary()->Load("assets/shaders/simplepbr_Static.glsl");
|
||||||
|
GetShaderLibrary()->Load("assets/shaders/simplepbr_Anim.glsl");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Renderer::WaitAndRender()
|
void Renderer::WaitAndRender()
|
||||||
|
|||||||
@ -5,6 +5,7 @@
|
|||||||
#ifndef RENDERER_H
|
#ifndef RENDERER_H
|
||||||
#define RENDERER_H
|
#define RENDERER_H
|
||||||
#include "RenderCommandQueue.h"
|
#include "RenderCommandQueue.h"
|
||||||
|
#include "Shader.h"
|
||||||
#include "Prism/Core/Application.h"
|
#include "Prism/Core/Application.h"
|
||||||
|
|
||||||
|
|
||||||
@ -25,6 +26,8 @@ namespace Prism
|
|||||||
|
|
||||||
static void Init();
|
static void Init();
|
||||||
|
|
||||||
|
static const Scope<ShaderLibrary>& GetShaderLibrary() { return Get().m_ShaderLibrary; }
|
||||||
|
|
||||||
static void* Submit(const RenderCommandFn func, const unsigned int size)
|
static void* Submit(const RenderCommandFn func, const unsigned int size)
|
||||||
{
|
{
|
||||||
return s_Instance->m_CommandQueue.Allocate(func, size);
|
return s_Instance->m_CommandQueue.Allocate(func, size);
|
||||||
@ -35,6 +38,7 @@ namespace Prism
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
static Renderer* s_Instance;
|
static Renderer* s_Instance;
|
||||||
|
Scope<ShaderLibrary> m_ShaderLibrary;
|
||||||
|
|
||||||
RenderCommandQueue m_CommandQueue;
|
RenderCommandQueue m_CommandQueue;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -9,16 +9,16 @@
|
|||||||
|
|
||||||
namespace Prism
|
namespace Prism
|
||||||
{
|
{
|
||||||
std::vector<Shader*> Shader::s_AllShaders;
|
std::vector<Ref<Shader>> Shader::s_AllShaders;
|
||||||
|
|
||||||
Shader* Shader::Create(const std::string& filepath)
|
Ref<Shader> Shader::Create(const std::string& filepath)
|
||||||
{
|
{
|
||||||
Shader* result = nullptr;
|
Ref<Shader> result = nullptr;
|
||||||
|
|
||||||
switch (RendererAPI::Current())
|
switch (RendererAPI::Current())
|
||||||
{
|
{
|
||||||
case RendererAPIType::None: return nullptr;
|
case RendererAPIType::None: return nullptr;
|
||||||
case RendererAPIType::OpenGL: result = new OpenGLShader(filepath);
|
case RendererAPIType::OpenGL: result = CreateRef<OpenGLShader>(filepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
s_AllShaders.push_back(result);
|
s_AllShaders.push_back(result);
|
||||||
@ -26,8 +26,43 @@ namespace Prism
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Shader*>& Shader::GetAllShaders()
|
std::vector<Ref<Shader>>& Shader::GetAllShaders()
|
||||||
{
|
{
|
||||||
return s_AllShaders;
|
return s_AllShaders;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ShaderLibrary::ShaderLibrary()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ShaderLibrary::~ShaderLibrary()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderLibrary::Add(const Ref<Shader>& shader)
|
||||||
|
{
|
||||||
|
auto& name = shader->GetName();
|
||||||
|
PM_CORE_ASSERT(m_Shaders.find(name) == m_Shaders.end());
|
||||||
|
m_Shaders[name] = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderLibrary::Load(const std::string& path)
|
||||||
|
{
|
||||||
|
auto shader = Ref<Shader>(Shader::Create(path));
|
||||||
|
auto& name = shader->GetName();
|
||||||
|
PM_CORE_ASSERT(m_Shaders.find(name) == m_Shaders.end());
|
||||||
|
m_Shaders[name] = shader;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ShaderLibrary::Load(const std::string& name, const std::string& path)
|
||||||
|
{
|
||||||
|
PM_CORE_ASSERT(m_Shaders.find(name) == m_Shaders.end());
|
||||||
|
m_Shaders[name] = Ref<Shader>(Shader::Create(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ref<Shader>& ShaderLibrary::Get(const std::string& name)
|
||||||
|
{
|
||||||
|
PM_CORE_ASSERT(m_Shaders.find(name) != m_Shaders.end());
|
||||||
|
return m_Shaders[name];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -122,11 +122,26 @@ namespace Prism
|
|||||||
|
|
||||||
virtual void AddShaderReloadedCallback(const ShaderReloadedCallback& callback) = 0;
|
virtual void AddShaderReloadedCallback(const ShaderReloadedCallback& callback) = 0;
|
||||||
|
|
||||||
static Shader* Create(const std::string& filepath);
|
static Ref<Shader> Create(const std::string& filepath);
|
||||||
static std::vector<Shader*>& GetAllShaders();
|
static std::vector<Ref<Shader>>& GetAllShaders();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static std::vector<Shader*> s_AllShaders;
|
static std::vector<Ref<Shader>> s_AllShaders;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ShaderLibrary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ShaderLibrary();
|
||||||
|
~ShaderLibrary();
|
||||||
|
|
||||||
|
void Add(const Ref<Shader>& shader);
|
||||||
|
void Load(const std::string& path);
|
||||||
|
void Load(const std::string& name, const std::string& path);
|
||||||
|
|
||||||
|
Ref<Shader>& Get(const std::string& name);
|
||||||
|
private:
|
||||||
|
std::unordered_map<std::string, Ref<Shader>> m_Shaders;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -111,13 +111,24 @@ DemoLayer::~DemoLayer()
|
|||||||
|
|
||||||
void DemoLayer::OnAttach()
|
void DemoLayer::OnAttach()
|
||||||
{
|
{
|
||||||
m_SimplePBRShader.reset(Prism::Shader::Create("assets/shaders/simplepbr.glsl"));
|
|
||||||
m_QuadShader.reset(Prism::Shader::Create("assets/shaders/quad.glsl"));
|
m_Framebuffer.reset(Prism::FrameBuffer::Create(1280, 720, Prism::FramebufferFormat::RGBA16F));
|
||||||
m_HDRShader.reset(Prism::Shader::Create("assets/shaders/hdr.glsl"));
|
m_FinalPresentBuffer.reset(Prism::FrameBuffer::Create(1280, 720, Prism::FramebufferFormat::RGBA8));
|
||||||
m_GridShader.reset(Prism::Shader::Create("assets/shaders/Grid.glsl"));
|
|
||||||
m_Mesh.reset(new Prism::Mesh("assets/models/m1911/m1911.fbx"));
|
m_QuadShader = Prism::Shader::Create("assets/shaders/quad.glsl");
|
||||||
m_SphereMesh.reset(new Prism::Mesh("assets/models/Sphere1m.fbx"));
|
m_HDRShader= Prism::Shader::Create("assets/shaders/hdr.glsl");
|
||||||
m_PlaneMesh.reset(new Prism::Mesh("assets/models/Plane1m.fbx"));
|
m_GridShader = Prism::Shader::Create("assets/shaders/Grid.glsl");
|
||||||
|
|
||||||
|
m_Mesh = Prism::CreateRef<Prism::Mesh>("assets/models/m1911/m1911.fbx");
|
||||||
|
m_MeshMaterial = Prism::CreateRef<Prism::MaterialInstance>(m_Mesh->GetMaterial());
|
||||||
|
|
||||||
|
m_SphereMesh = Prism::CreateRef<Prism::Mesh>("assets/models/Sphere1m.fbx");
|
||||||
|
m_PlaneMesh = Prism::CreateRef<Prism::Mesh>("assets/models/Plane1m.fbx");
|
||||||
|
|
||||||
|
m_GridShader = Prism::Shader::Create("assets/shaders/Grid.glsl");
|
||||||
|
m_GridMaterial = Prism::MaterialInstance::Create(Prism::Material::Create(m_GridShader));
|
||||||
|
m_GridMaterial->Set("u_Scale", m_GridScale);
|
||||||
|
m_GridMaterial->Set("u_Res", m_GridSize);
|
||||||
|
|
||||||
// Editor
|
// Editor
|
||||||
m_CheckerboardTex.reset(Prism::Texture2D::Create("assets/editor/Checkerboard.tga"));
|
m_CheckerboardTex.reset(Prism::Texture2D::Create("assets/editor/Checkerboard.tga"));
|
||||||
@ -127,16 +138,12 @@ void DemoLayer::OnAttach()
|
|||||||
m_EnvironmentIrradiance.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Irradiance.tga"));
|
m_EnvironmentIrradiance.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Irradiance.tga"));
|
||||||
m_BRDFLUT.reset(Prism::Texture2D::Create("assets/textures/BRDF_LUT.tga"));
|
m_BRDFLUT.reset(Prism::Texture2D::Create("assets/textures/BRDF_LUT.tga"));
|
||||||
|
|
||||||
m_Framebuffer.reset(Prism::FrameBuffer::Create(1280, 720, Prism::FramebufferFormat::RGBA16F));
|
|
||||||
m_FinalPresentBuffer.reset(Prism::FrameBuffer::Create(1280, 720, Prism::FramebufferFormat::RGBA8));
|
|
||||||
|
|
||||||
m_PBRMaterial.reset(new Prism::Material(m_SimplePBRShader));
|
|
||||||
|
|
||||||
float x = -4.0f;
|
float x = -4.0f;
|
||||||
float roughness = 0.0f;
|
float roughness = 0.0f;
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
Prism::Ref<Prism::MaterialInstance> mi(new Prism::MaterialInstance(m_PBRMaterial));
|
Prism::Ref<Prism::MaterialInstance> mi = Prism::CreateRef<Prism::MaterialInstance>(m_SphereMesh->GetMaterial());
|
||||||
mi->Set("u_Metalness", 1.0f);
|
mi->Set("u_Metalness", 1.0f);
|
||||||
mi->Set("u_Roughness", roughness);
|
mi->Set("u_Roughness", roughness);
|
||||||
mi->Set("u_ModelMatrix", glm::translate(glm::mat4(1.0f), glm::vec3(x, 0.0f, 0.0f)));
|
mi->Set("u_ModelMatrix", glm::translate(glm::mat4(1.0f), glm::vec3(x, 0.0f, 0.0f)));
|
||||||
@ -149,7 +156,7 @@ void DemoLayer::OnAttach()
|
|||||||
roughness = 0.0f;
|
roughness = 0.0f;
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
Prism::Ref<Prism::MaterialInstance> mi(new Prism::MaterialInstance(m_PBRMaterial));
|
Prism::Ref<Prism::MaterialInstance> mi = Prism::CreateRef<Prism::MaterialInstance>(m_SphereMesh->GetMaterial());
|
||||||
mi->Set("u_Metalness", 0.0f);
|
mi->Set("u_Metalness", 0.0f);
|
||||||
mi->Set("u_Roughness", roughness);
|
mi->Set("u_Roughness", roughness);
|
||||||
mi->Set("u_ModelMatrix", translate(glm::mat4(1.0f), glm::vec3(x, 1.2f, 0.0f)));
|
mi->Set("u_ModelMatrix", translate(glm::mat4(1.0f), glm::vec3(x, 1.2f, 0.0f)));
|
||||||
@ -212,10 +219,6 @@ void DemoLayer::OnUpdate(const Prism::TimeStep deltaTime)
|
|||||||
m_Framebuffer->Bind();
|
m_Framebuffer->Bind();
|
||||||
Renderer::Clear(m_ClearColor[0], m_ClearColor[1], m_ClearColor[2], m_ClearColor[3]);
|
Renderer::Clear(m_ClearColor[0], m_ClearColor[1], m_ClearColor[2], m_ClearColor[3]);
|
||||||
|
|
||||||
Prism::UniformBufferDeclaration<sizeof(mat4), 1> quadShaderUB;
|
|
||||||
quadShaderUB.Push("u_InverseVP", inverse(viewProjection));
|
|
||||||
m_QuadShader->UploadUniformBuffer(quadShaderUB);
|
|
||||||
|
|
||||||
m_QuadShader->Bind();
|
m_QuadShader->Bind();
|
||||||
m_QuadShader->SetMat4("u_InverseVP", inverse(viewProjection));
|
m_QuadShader->SetMat4("u_InverseVP", inverse(viewProjection));
|
||||||
m_EnvironmentCubeMap->Bind(0);
|
m_EnvironmentCubeMap->Bind(0);
|
||||||
@ -224,72 +227,72 @@ void DemoLayer::OnUpdate(const Prism::TimeStep deltaTime)
|
|||||||
Renderer::DrawIndexed(m_IndexBuffer->GetCount(), false);
|
Renderer::DrawIndexed(m_IndexBuffer->GetCount(), false);
|
||||||
|
|
||||||
|
|
||||||
m_PBRMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color);
|
m_MeshMaterial->Set("u_AlbedoColor", m_AlbedoInput.Color);
|
||||||
m_PBRMaterial->Set("u_Metalness", m_MetalnessInput.Value);
|
m_MeshMaterial->Set("u_Metalness", m_MetalnessInput.Value);
|
||||||
m_PBRMaterial->Set("u_Roughness", m_RoughnessInput.Value);
|
m_MeshMaterial->Set("u_Roughness", m_RoughnessInput.Value);
|
||||||
m_PBRMaterial->Set("u_ViewProjectionMatrix", viewProjection);
|
m_MeshMaterial->Set("u_ViewProjectionMatrix", viewProjection);
|
||||||
m_PBRMaterial->Set("u_ModelMatrix", scale(mat4(1.0f), vec3(m_MeshScale)));
|
m_MeshMaterial->Set("u_ModelMatrix", scale(mat4(1.0f), vec3(m_MeshScale)));
|
||||||
m_PBRMaterial->Set("lights", m_Light);
|
m_MeshMaterial->Set("lights", m_Light);
|
||||||
m_PBRMaterial->Set("u_CameraPosition", m_Camera.GetPosition());
|
m_MeshMaterial->Set("u_CameraPosition", m_Camera.GetPosition());
|
||||||
m_PBRMaterial->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f);
|
m_MeshMaterial->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f);
|
||||||
m_PBRMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
|
m_MeshMaterial->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
|
||||||
m_PBRMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
|
m_MeshMaterial->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
|
||||||
m_PBRMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
|
m_MeshMaterial->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
|
||||||
m_PBRMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f);
|
m_MeshMaterial->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f);
|
||||||
m_PBRMaterial->Set("u_EnvMapRotation", m_EnvMapRotation);
|
m_MeshMaterial->Set("u_EnvMapRotation", m_EnvMapRotation);
|
||||||
|
|
||||||
m_PBRMaterial->Set("u_EnvRadianceTex", m_EnvironmentCubeMap);
|
m_MeshMaterial->Set("u_EnvRadianceTex", m_EnvironmentCubeMap);
|
||||||
m_PBRMaterial->Set("u_EnvIrradianceTex", m_EnvironmentIrradiance);
|
m_MeshMaterial->Set("u_EnvIrradianceTex", m_EnvironmentIrradiance);
|
||||||
m_PBRMaterial->Set("u_BRDFLUTTexture", m_BRDFLUT);
|
m_MeshMaterial->Set("u_BRDFLUTTexture", m_BRDFLUT);
|
||||||
/*
|
|
||||||
Prism::UniformBufferDeclaration<sizeof(mat4) * 2 + sizeof(vec3) * 4 + sizeof(float) * 8, 14> simplePbrShaderUB;
|
m_SphereMesh->GetMaterial()->Set("u_AlbedoColor", m_AlbedoInput.Color);
|
||||||
simplePbrShaderUB.Push("u_ViewProjectionMatrix", viewProjection);
|
m_SphereMesh->GetMaterial()->Set("u_Metalness", m_MetalnessInput.Value);
|
||||||
simplePbrShaderUB.Push("u_ModelMatrix", mat4(1.0f));
|
m_SphereMesh->GetMaterial()->Set("u_Roughness", m_RoughnessInput.Value);
|
||||||
simplePbrShaderUB.Push("u_AlbedoColor", m_AlbedoInput.Color);
|
m_SphereMesh->GetMaterial()->Set("u_ViewProjectionMatrix", viewProjection);
|
||||||
simplePbrShaderUB.Push("u_Metalness", m_MetalnessInput.Value);
|
m_SphereMesh->GetMaterial()->Set("u_ModelMatrix", scale(mat4(1.0f), vec3(m_MeshScale)));
|
||||||
simplePbrShaderUB.Push("u_Roughness", m_RoughnessInput.Value);
|
m_SphereMesh->GetMaterial()->Set("lights", m_Light);
|
||||||
simplePbrShaderUB.Push("lights.Direction", m_Light.Direction);
|
m_SphereMesh->GetMaterial()->Set("u_CameraPosition", m_Camera.GetPosition());
|
||||||
simplePbrShaderUB.Push("lights.Radiance", m_Light.Radiance * m_LightMultiplier);
|
m_SphereMesh->GetMaterial()->Set("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f);
|
||||||
simplePbrShaderUB.Push("u_CameraPosition", m_Camera.GetPosition());
|
m_SphereMesh->GetMaterial()->Set("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
|
||||||
simplePbrShaderUB.Push("u_RadiancePrefilter", m_RadiancePrefilter ? 1.0f : 0.0f);
|
m_SphereMesh->GetMaterial()->Set("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
|
||||||
simplePbrShaderUB.Push("u_AlbedoTexToggle", m_AlbedoInput.UseTexture ? 1.0f : 0.0f);
|
m_SphereMesh->GetMaterial()->Set("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
|
||||||
simplePbrShaderUB.Push("u_NormalTexToggle", m_NormalInput.UseTexture ? 1.0f : 0.0f);
|
m_SphereMesh->GetMaterial()->Set("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f);
|
||||||
simplePbrShaderUB.Push("u_MetalnessTexToggle", m_MetalnessInput.UseTexture ? 1.0f : 0.0f);
|
m_SphereMesh->GetMaterial()->Set("u_EnvMapRotation", m_EnvMapRotation);
|
||||||
simplePbrShaderUB.Push("u_RoughnessTexToggle", m_RoughnessInput.UseTexture ? 1.0f : 0.0f);
|
m_SphereMesh->GetMaterial()->Set("u_EnvRadianceTex", m_EnvironmentCubeMap);
|
||||||
simplePbrShaderUB.Push("u_EnvMapRotation", m_EnvMapRotation);
|
m_SphereMesh->GetMaterial()->Set("u_EnvIrradianceTex", m_EnvironmentIrradiance);
|
||||||
m_SimplePBRShader->UploadUniformBuffer(simplePbrShaderUB);
|
m_SphereMesh->GetMaterial()->Set("u_BRDFLUTTexture", m_BRDFLUT);
|
||||||
|
|
||||||
m_EnvironmentCubeMap->Bind(10);
|
|
||||||
m_EnvironmentIrradiance->Bind(11);
|
|
||||||
m_BRDFLUT->Bind(15);
|
|
||||||
m_SimplePBRShader->Bind();
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
if (m_AlbedoInput.TextureMap)
|
if (m_AlbedoInput.TextureMap)
|
||||||
m_PBRMaterial->Set("u_AlbedoTexture", m_AlbedoInput.TextureMap);
|
m_MeshMaterial->Set("u_AlbedoTexture", m_AlbedoInput.TextureMap);
|
||||||
if (m_NormalInput.TextureMap)
|
if (m_NormalInput.TextureMap)
|
||||||
m_PBRMaterial->Set("u_NormalTexture", m_NormalInput.TextureMap);
|
m_MeshMaterial->Set("u_NormalTexture", m_NormalInput.TextureMap);
|
||||||
if (m_MetalnessInput.TextureMap)
|
if (m_MetalnessInput.TextureMap)
|
||||||
m_PBRMaterial->Set("u_MetalnessTexture", m_MetalnessInput.TextureMap);
|
m_MeshMaterial->Set("u_MetalnessTexture", m_MetalnessInput.TextureMap);
|
||||||
if (m_RoughnessInput.TextureMap)
|
if (m_RoughnessInput.TextureMap)
|
||||||
m_PBRMaterial->Set("u_RoughnessTexture", m_RoughnessInput.TextureMap);
|
m_MeshMaterial->Set("u_RoughnessTexture", m_RoughnessInput.TextureMap);
|
||||||
|
|
||||||
if (m_Scene == Scene::Spheres)
|
if (m_Scene == Scene::Spheres)
|
||||||
{
|
{
|
||||||
// Metals
|
// Metals
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
|
m_SphereMesh->Render(deltaTime, glm::mat4(1.0f), m_MetalSphereMaterialInstances[i]);
|
||||||
|
/*
|
||||||
m_MetalSphereMaterialInstances[i]->Bind();
|
m_MetalSphereMaterialInstances[i]->Bind();
|
||||||
m_SphereMesh->Render(deltaTime, m_SimplePBRShader.get());
|
m_SphereMesh->Render(deltaTime, m_SimplePBRShader.get());
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
// Dielectrics
|
// Dielectrics
|
||||||
for (int i = 0; i < 8; i++)
|
for (int i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
|
m_SphereMesh->Render(deltaTime, glm::mat4(1.0f), m_DielectricSphereMaterialInstances[i]);
|
||||||
|
/*
|
||||||
m_DielectricSphereMaterialInstances[i]->Bind();
|
m_DielectricSphereMaterialInstances[i]->Bind();
|
||||||
m_SphereMesh->Render(deltaTime, m_SimplePBRShader.get());
|
m_SphereMesh->Render(deltaTime, m_SimplePBRShader.get());
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -297,16 +300,13 @@ void DemoLayer::OnUpdate(const Prism::TimeStep deltaTime)
|
|||||||
{
|
{
|
||||||
if (m_Mesh)
|
if (m_Mesh)
|
||||||
{
|
{
|
||||||
m_PBRMaterial->Bind();
|
m_Mesh->Render(deltaTime, scale(mat4(1.0f), vec3(m_MeshScale)), m_MeshMaterial);
|
||||||
m_Mesh->Render(deltaTime, m_SimplePBRShader.get());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_GridShader->Bind();
|
m_GridMaterial->Set("u_MVP", viewProjection * glm::scale(glm::mat4(1.0f), glm::vec3(16.0f)));
|
||||||
m_GridShader->SetMat4("u_MVP", viewProjection * glm::scale(glm::mat4(1.0f), glm::vec3(16.0f)));
|
m_PlaneMesh->Render(deltaTime, m_GridMaterial);
|
||||||
m_GridShader->SetFloat("u_Scale", m_GridScale);
|
|
||||||
m_GridShader->SetFloat("u_Res", m_GridSize);
|
|
||||||
m_PlaneMesh->Render(deltaTime, m_GridShader.get());
|
|
||||||
m_Framebuffer->Unbind();
|
m_Framebuffer->Unbind();
|
||||||
|
|
||||||
m_FinalPresentBuffer->Bind();
|
m_FinalPresentBuffer->Bind();
|
||||||
@ -633,10 +633,20 @@ void DemoLayer::OnImGuiRender()
|
|||||||
m_FinalPresentBuffer->Resize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
m_FinalPresentBuffer->Resize((uint32_t)viewportSize.x, (uint32_t)viewportSize.y);
|
||||||
m_Camera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
|
m_Camera.SetProjectionMatrix(glm::perspectiveFov(glm::radians(45.0f), viewportSize.x, viewportSize.y, 0.1f, 10000.0f));
|
||||||
ImGui::Image((ImTextureRef)m_FinalPresentBuffer->GetColorAttachmentRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
ImGui::Image((ImTextureRef)m_FinalPresentBuffer->GetColorAttachmentRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
||||||
// ImGui::Image((void*)m_Framebuffer->GetColorAttachmentRendererID(), viewportSize, { 0, 1 }, { 1, 0 });
|
|
||||||
ImGui::End();
|
ImGui::End();
|
||||||
ImGui::PopStyleVar();
|
ImGui::PopStyleVar();
|
||||||
|
|
||||||
|
ImGui::Begin("Log");
|
||||||
|
const auto& cameraPos = m_Camera.GetPosition();
|
||||||
|
ImGui::Text("cameraPos: (%.2f, %.2f, %.2f)", cameraPos.x, cameraPos.y, cameraPos.z);
|
||||||
|
|
||||||
|
const auto& Direct = m_Camera.GetForwardDirection();
|
||||||
|
ImGui::Text("forward Vec: (%.2f, %.2f, %.2f)", Direct.x, Direct.y, Direct.z);
|
||||||
|
|
||||||
|
const auto& distance = m_Camera.GetDistance();
|
||||||
|
ImGui::Text("distance: %.3f", distance);
|
||||||
|
ImGui::End();
|
||||||
|
|
||||||
if (m_Mesh)
|
if (m_Mesh)
|
||||||
m_Mesh->OnImGuiRender();
|
m_Mesh->OnImGuiRender();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,15 +26,16 @@ public:
|
|||||||
private:
|
private:
|
||||||
float m_ClearColor[4];
|
float m_ClearColor[4];
|
||||||
|
|
||||||
Prism::Ref<Prism::Shader> m_SimplePBRShader;
|
Prism::Ref<Prism::Shader> m_QuadShader;
|
||||||
Prism::Scope<Prism::Shader> m_QuadShader;
|
Prism::Ref<Prism::Shader> m_HDRShader;
|
||||||
Prism::Scope<Prism::Shader> m_HDRShader;
|
Prism::Ref<Prism::Shader> m_GridShader;
|
||||||
Prism::Scope<Prism::Shader> m_GridShader;
|
Prism::Ref<Prism::Mesh> m_Mesh;
|
||||||
Prism::Scope<Prism::Mesh> m_Mesh;
|
Prism::Ref<Prism::Mesh> m_SphereMesh, m_PlaneMesh;
|
||||||
Prism::Scope<Prism::Mesh> m_SphereMesh, m_PlaneMesh;
|
|
||||||
Prism::Ref<Prism::Texture2D> m_BRDFLUT;
|
Prism::Ref<Prism::Texture2D> m_BRDFLUT;
|
||||||
|
|
||||||
Prism::Ref<Prism::Material> m_PBRMaterial;
|
Prism::Ref<Prism::MaterialInstance> m_MeshMaterial;
|
||||||
|
Prism::Ref<Prism::MaterialInstance> m_GridMaterial;
|
||||||
|
|
||||||
std::vector<Prism::Ref<Prism::MaterialInstance>> m_MetalSphereMaterialInstances;
|
std::vector<Prism::Ref<Prism::MaterialInstance>> m_MetalSphereMaterialInstances;
|
||||||
std::vector<Prism::Ref<Prism::MaterialInstance>> m_DielectricSphereMaterialInstances;
|
std::vector<Prism::Ref<Prism::MaterialInstance>> m_DielectricSphereMaterialInstances;
|
||||||
|
|
||||||
|
|||||||
@ -174,9 +174,9 @@ void TestLayer::OnAttach()
|
|||||||
|
|
||||||
m_SkyBoxTextureCube.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Radiance.tga"));
|
m_SkyBoxTextureCube.reset(Prism::TextureCube::Create("assets/textures/environments/Arches_E_PineTree_Radiance.tga"));
|
||||||
|
|
||||||
m_SkyboxShader.reset(Prism::Shader::Create("assets/shaders/quad.glsl"));
|
m_SkyboxShader = Prism::Shader::Create("assets/shaders/quad.glsl");
|
||||||
m_Shader.reset(Prism::Shader::Create("assets/shaders/demo.glsl"));
|
m_Shader = Prism::Shader::Create("assets/shaders/demo.glsl");
|
||||||
m_HDRShader.reset(Prism::Shader::Create("assets/shaders/hdr.glsl"));
|
m_HDRShader = Prism::Shader::Create("assets/shaders/hdr.glsl");
|
||||||
|
|
||||||
m_Mesh = std::make_unique<Prism::Mesh>("assets/meshes/cerberus.fbx");
|
m_Mesh = std::make_unique<Prism::Mesh>("assets/meshes/cerberus.fbx");
|
||||||
}
|
}
|
||||||
@ -210,7 +210,7 @@ void TestLayer::OnUpdate(Prism::TimeStep deltaTime)
|
|||||||
|
|
||||||
m_Shader->Bind();
|
m_Shader->Bind();
|
||||||
|
|
||||||
m_Mesh->Render(deltaTime, m_Shader.get());
|
// m_Mesh->Render(deltaTime, m_Shader);
|
||||||
// m_VertexBuffer->Bind();
|
// m_VertexBuffer->Bind();
|
||||||
// m_IndexBuffer->Bind();
|
// m_IndexBuffer->Bind();
|
||||||
|
|
||||||
|
|||||||
@ -28,17 +28,17 @@ private:
|
|||||||
glm::vec4 m_clearColor = glm::vec4(0.1f, 0.1f, 0.1f, 1.0f);
|
glm::vec4 m_clearColor = glm::vec4(0.1f, 0.1f, 0.1f, 1.0f);
|
||||||
glm::vec4 m_TriangleColor = glm::vec4(1.0f);
|
glm::vec4 m_TriangleColor = glm::vec4(1.0f);
|
||||||
|
|
||||||
std::unique_ptr<Prism::FrameBuffer> m_FrameBuffer, m_FinalPresentBuffer;
|
Prism::Ref<Prism::FrameBuffer> m_FrameBuffer, m_FinalPresentBuffer;
|
||||||
std::unique_ptr<Prism::VertexBuffer> m_VertexBuffer;
|
Prism::Ref<Prism::VertexBuffer> m_VertexBuffer;
|
||||||
std::unique_ptr<Prism::IndexBuffer> m_IndexBuffer;
|
Prism::Ref<Prism::IndexBuffer> m_IndexBuffer;
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<Prism::TextureCube> m_SkyBoxTextureCube;
|
Prism::Ref<Prism::TextureCube> m_SkyBoxTextureCube;
|
||||||
|
|
||||||
std::unique_ptr<Prism::Shader> m_SkyboxShader;
|
Prism::Ref<Prism::Shader> m_SkyboxShader;
|
||||||
std::unique_ptr<Prism::Shader> m_Shader;
|
Prism::Ref<Prism::Shader> m_Shader;
|
||||||
std::unique_ptr<Prism::Shader> m_HDRShader;
|
Prism::Ref<Prism::Shader> m_HDRShader;
|
||||||
std::unique_ptr<Prism::Mesh> m_Mesh;
|
Prism::Ref<Prism::Mesh> m_Mesh;
|
||||||
|
|
||||||
Prism::Camera m_Camera;
|
Prism::Camera m_Camera;
|
||||||
|
|
||||||
|
|||||||
@ -18,8 +18,8 @@ public:
|
|||||||
|
|
||||||
virtual void OnInit() override
|
virtual void OnInit() override
|
||||||
{
|
{
|
||||||
PushLayer(new TestLayer());
|
// PushLayer(new TestLayer());
|
||||||
// PushLayer(new DemoLayer());
|
PushLayer(new DemoLayer());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -23,7 +23,6 @@ void main()
|
|||||||
|
|
||||||
layout(location = 0) out vec4 color;
|
layout(location = 0) out vec4 color;
|
||||||
|
|
||||||
uniform sampler2D u_Texture;
|
|
||||||
uniform float u_Scale;
|
uniform float u_Scale;
|
||||||
uniform float u_Res;
|
uniform float u_Res;
|
||||||
|
|
||||||
|
|||||||
321
Sandbox/assets/shaders/simplepbr_Static.glsl
Normal file
321
Sandbox/assets/shaders/simplepbr_Static.glsl
Normal file
@ -0,0 +1,321 @@
|
|||||||
|
// -----------------------------
|
||||||
|
// -- Hazel Engine PBR shader --
|
||||||
|
// -----------------------------
|
||||||
|
// Note: this shader is still very much in progress. There are likely many bugs and future additions that will go in.
|
||||||
|
// Currently heavily updated.
|
||||||
|
//
|
||||||
|
// References upon which this is based:
|
||||||
|
// - Unreal Engine 4 PBR notes (https://blog.selfshadow.com/publications/s2013-shading-course/karis/s2013_pbs_epic_notes_v2.pdf)
|
||||||
|
// - Frostbite's SIGGRAPH 2014 paper (https://seblagarde.wordpress.com/2015/07/14/siggraph-2014-moving-frostbite-to-physically-based-rendering/)
|
||||||
|
// - Michał Siejak's PBR project (https://github.com/Nadrin)
|
||||||
|
// - My implementation from years ago in the Sparky engine (https://github.com/TheCherno/Sparky)
|
||||||
|
#type vertex
|
||||||
|
#version 430 core
|
||||||
|
|
||||||
|
layout(location = 0) in vec3 a_Position;
|
||||||
|
layout(location = 1) in vec3 a_Normal;
|
||||||
|
layout(location = 2) in vec3 a_Tangent;
|
||||||
|
layout(location = 3) in vec3 a_Binormal;
|
||||||
|
layout(location = 4) in vec2 a_TexCoord;
|
||||||
|
|
||||||
|
uniform mat4 u_ViewProjectionMatrix;
|
||||||
|
uniform mat4 u_ModelMatrix;
|
||||||
|
|
||||||
|
out VertexOutput
|
||||||
|
{
|
||||||
|
vec3 WorldPosition;
|
||||||
|
vec3 Normal;
|
||||||
|
vec2 TexCoord;
|
||||||
|
mat3 WorldNormals;
|
||||||
|
vec3 Binormal;
|
||||||
|
} vs_Output;
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
vs_Output.WorldPosition = vec3(u_ModelMatrix * vec4(a_Position, 1.0));
|
||||||
|
vs_Output.Normal = a_Normal;
|
||||||
|
vs_Output.TexCoord = vec2(a_TexCoord.x, 1.0 - a_TexCoord.y);
|
||||||
|
vs_Output.WorldNormals = mat3(u_ModelMatrix) * mat3(a_Tangent, a_Binormal, a_Normal);
|
||||||
|
vs_Output.Binormal = a_Binormal;
|
||||||
|
|
||||||
|
gl_Position = u_ViewProjectionMatrix * u_ModelMatrix * vec4(a_Position, 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#type fragment
|
||||||
|
#version 430 core
|
||||||
|
|
||||||
|
const float PI = 3.141592;
|
||||||
|
const float Epsilon = 0.00001;
|
||||||
|
|
||||||
|
const int LightCount = 1;
|
||||||
|
|
||||||
|
// Constant normal incidence Fresnel factor for all dielectrics.
|
||||||
|
const vec3 Fdielectric = vec3(0.04);
|
||||||
|
|
||||||
|
struct Light {
|
||||||
|
vec3 Direction;
|
||||||
|
vec3 Radiance;
|
||||||
|
};
|
||||||
|
|
||||||
|
in VertexOutput
|
||||||
|
{
|
||||||
|
vec3 WorldPosition;
|
||||||
|
vec3 Normal;
|
||||||
|
vec2 TexCoord;
|
||||||
|
mat3 WorldNormals;
|
||||||
|
vec3 Binormal;
|
||||||
|
} vs_Input;
|
||||||
|
|
||||||
|
layout(location = 0) out vec4 color;
|
||||||
|
|
||||||
|
uniform Light lights;
|
||||||
|
uniform vec3 u_CameraPosition;
|
||||||
|
|
||||||
|
// PBR texture inputs
|
||||||
|
uniform sampler2D u_AlbedoTexture;
|
||||||
|
uniform sampler2D u_NormalTexture;
|
||||||
|
uniform sampler2D u_MetalnessTexture;
|
||||||
|
uniform sampler2D u_RoughnessTexture;
|
||||||
|
|
||||||
|
// Environment maps
|
||||||
|
uniform samplerCube u_EnvRadianceTex;
|
||||||
|
uniform samplerCube u_EnvIrradianceTex;
|
||||||
|
|
||||||
|
// BRDF LUT
|
||||||
|
uniform sampler2D u_BRDFLUTTexture;
|
||||||
|
|
||||||
|
uniform vec3 u_AlbedoColor;
|
||||||
|
uniform float u_Metalness;
|
||||||
|
uniform float u_Roughness;
|
||||||
|
|
||||||
|
uniform float u_EnvMapRotation;
|
||||||
|
|
||||||
|
// Toggles
|
||||||
|
uniform float u_RadiancePrefilter;
|
||||||
|
uniform float u_AlbedoTexToggle;
|
||||||
|
uniform float u_NormalTexToggle;
|
||||||
|
uniform float u_MetalnessTexToggle;
|
||||||
|
uniform float u_RoughnessTexToggle;
|
||||||
|
|
||||||
|
struct PBRParameters
|
||||||
|
{
|
||||||
|
vec3 Albedo;
|
||||||
|
float Roughness;
|
||||||
|
float Metalness;
|
||||||
|
|
||||||
|
vec3 Normal;
|
||||||
|
vec3 View;
|
||||||
|
float NdotV;
|
||||||
|
};
|
||||||
|
|
||||||
|
PBRParameters m_Params;
|
||||||
|
|
||||||
|
// GGX/Towbridge-Reitz normal distribution function.
|
||||||
|
// Uses Disney's reparametrization of alpha = roughness^2
|
||||||
|
float ndfGGX(float cosLh, float roughness)
|
||||||
|
{
|
||||||
|
float alpha = roughness * roughness;
|
||||||
|
float alphaSq = alpha * alpha;
|
||||||
|
|
||||||
|
float denom = (cosLh * cosLh) * (alphaSq - 1.0) + 1.0;
|
||||||
|
return alphaSq / (PI * denom * denom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single term for separable Schlick-GGX below.
|
||||||
|
float gaSchlickG1(float cosTheta, float k)
|
||||||
|
{
|
||||||
|
return cosTheta / (cosTheta * (1.0 - k) + k);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Schlick-GGX approximation of geometric attenuation function using Smith's method.
|
||||||
|
float gaSchlickGGX(float cosLi, float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float r = roughness + 1.0;
|
||||||
|
float k = (r * r) / 8.0; // Epic suggests using this roughness remapping for analytic lights.
|
||||||
|
return gaSchlickG1(cosLi, k) * gaSchlickG1(NdotV, k);
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySchlickGGX(float NdotV, float roughness)
|
||||||
|
{
|
||||||
|
float r = (roughness + 1.0);
|
||||||
|
float k = (r*r) / 8.0;
|
||||||
|
|
||||||
|
float nom = NdotV;
|
||||||
|
float denom = NdotV * (1.0 - k) + k;
|
||||||
|
|
||||||
|
return nom / denom;
|
||||||
|
}
|
||||||
|
|
||||||
|
float GeometrySmith(vec3 N, vec3 V, vec3 L, float roughness)
|
||||||
|
{
|
||||||
|
float NdotV = max(dot(N, V), 0.0);
|
||||||
|
float NdotL = max(dot(N, L), 0.0);
|
||||||
|
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
|
||||||
|
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
|
||||||
|
|
||||||
|
return ggx1 * ggx2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shlick's approximation of the Fresnel factor.
|
||||||
|
vec3 fresnelSchlick(vec3 F0, float cosTheta)
|
||||||
|
{
|
||||||
|
return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 fresnelSchlickRoughness(vec3 F0, float cosTheta, float roughness)
|
||||||
|
{
|
||||||
|
return F0 + (max(vec3(1.0 - roughness), F0) - F0) * pow(1.0 - cosTheta, 5.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------
|
||||||
|
// The following code (from Unreal Engine 4's paper) shows how to filter the environment map
|
||||||
|
// for different roughnesses. This is mean to be computed offline and stored in cube map mips,
|
||||||
|
// so turning this on online will cause poor performance
|
||||||
|
float RadicalInverse_VdC(uint bits)
|
||||||
|
{
|
||||||
|
bits = (bits << 16u) | (bits >> 16u);
|
||||||
|
bits = ((bits & 0x55555555u) << 1u) | ((bits & 0xAAAAAAAAu) >> 1u);
|
||||||
|
bits = ((bits & 0x33333333u) << 2u) | ((bits & 0xCCCCCCCCu) >> 2u);
|
||||||
|
bits = ((bits & 0x0F0F0F0Fu) << 4u) | ((bits & 0xF0F0F0F0u) >> 4u);
|
||||||
|
bits = ((bits & 0x00FF00FFu) << 8u) | ((bits & 0xFF00FF00u) >> 8u);
|
||||||
|
return float(bits) * 2.3283064365386963e-10; // / 0x100000000
|
||||||
|
}
|
||||||
|
|
||||||
|
vec2 Hammersley(uint i, uint N)
|
||||||
|
{
|
||||||
|
return vec2(float(i)/float(N), RadicalInverse_VdC(i));
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 ImportanceSampleGGX(vec2 Xi, float Roughness, vec3 N)
|
||||||
|
{
|
||||||
|
float a = Roughness * Roughness;
|
||||||
|
float Phi = 2 * PI * Xi.x;
|
||||||
|
float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*a - 1) * Xi.y ) );
|
||||||
|
float SinTheta = sqrt( 1 - CosTheta * CosTheta );
|
||||||
|
vec3 H;
|
||||||
|
H.x = SinTheta * cos( Phi );
|
||||||
|
H.y = SinTheta * sin( Phi );
|
||||||
|
H.z = CosTheta;
|
||||||
|
vec3 UpVector = abs(N.z) < 0.999 ? vec3(0,0,1) : vec3(1,0,0);
|
||||||
|
vec3 TangentX = normalize( cross( UpVector, N ) );
|
||||||
|
vec3 TangentY = cross( N, TangentX );
|
||||||
|
// Tangent to world space
|
||||||
|
return TangentX * H.x + TangentY * H.y + N * H.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
float TotalWeight = 0.0;
|
||||||
|
|
||||||
|
vec3 PrefilterEnvMap(float Roughness, vec3 R)
|
||||||
|
{
|
||||||
|
vec3 N = R;
|
||||||
|
vec3 V = R;
|
||||||
|
vec3 PrefilteredColor = vec3(0.0);
|
||||||
|
int NumSamples = 1024;
|
||||||
|
for(int i = 0; i < NumSamples; i++)
|
||||||
|
{
|
||||||
|
vec2 Xi = Hammersley(i, NumSamples);
|
||||||
|
vec3 H = ImportanceSampleGGX(Xi, Roughness, N);
|
||||||
|
vec3 L = 2 * dot(V, H) * H - V;
|
||||||
|
float NoL = clamp(dot(N, L), 0.0, 1.0);
|
||||||
|
if (NoL > 0)
|
||||||
|
{
|
||||||
|
PrefilteredColor += texture(u_EnvRadianceTex, L).rgb * NoL;
|
||||||
|
TotalWeight += NoL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PrefilteredColor / TotalWeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
vec3 RotateVectorAboutY(float angle, vec3 vec)
|
||||||
|
{
|
||||||
|
angle = radians(angle);
|
||||||
|
mat3x3 rotationMatrix ={vec3(cos(angle),0.0,sin(angle)),
|
||||||
|
vec3(0.0,1.0,0.0),
|
||||||
|
vec3(-sin(angle),0.0,cos(angle))};
|
||||||
|
return rotationMatrix * vec;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 Lighting(vec3 F0)
|
||||||
|
{
|
||||||
|
vec3 result = vec3(0.0);
|
||||||
|
for(int i = 0; i < LightCount; i++)
|
||||||
|
{
|
||||||
|
vec3 Li = -lights.Direction;
|
||||||
|
vec3 Lradiance = lights.Radiance;
|
||||||
|
vec3 Lh = normalize(Li + m_Params.View);
|
||||||
|
|
||||||
|
// Calculate angles between surface normal and various light vectors.
|
||||||
|
float cosLi = max(0.0, dot(m_Params.Normal, Li));
|
||||||
|
float cosLh = max(0.0, dot(m_Params.Normal, Lh));
|
||||||
|
|
||||||
|
vec3 F = fresnelSchlick(F0, max(0.0, dot(Lh, m_Params.View)));
|
||||||
|
float D = ndfGGX(cosLh, m_Params.Roughness);
|
||||||
|
float G = gaSchlickGGX(cosLi, m_Params.NdotV, m_Params.Roughness);
|
||||||
|
|
||||||
|
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||||
|
vec3 diffuseBRDF = kd * m_Params.Albedo;
|
||||||
|
|
||||||
|
// Cook-Torrance
|
||||||
|
vec3 specularBRDF = (F * D * G) / max(Epsilon, 4.0 * cosLi * m_Params.NdotV);
|
||||||
|
|
||||||
|
result += (diffuseBRDF + specularBRDF) * Lradiance * cosLi;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 IBL(vec3 F0, vec3 Lr)
|
||||||
|
{
|
||||||
|
vec3 irradiance = texture(u_EnvIrradianceTex, m_Params.Normal).rgb;
|
||||||
|
vec3 F = fresnelSchlickRoughness(F0, m_Params.NdotV, m_Params.Roughness);
|
||||||
|
vec3 kd = (1.0 - F) * (1.0 - m_Params.Metalness);
|
||||||
|
vec3 diffuseIBL = m_Params.Albedo * irradiance;
|
||||||
|
|
||||||
|
int u_EnvRadianceTexLevels = textureQueryLevels(u_EnvRadianceTex);
|
||||||
|
float NoV = clamp(m_Params.NdotV, 0.0, 1.0);
|
||||||
|
vec3 R = 2.0 * dot(m_Params.View, m_Params.Normal) * m_Params.Normal - m_Params.View;
|
||||||
|
vec3 specularIrradiance = vec3(0.0);
|
||||||
|
|
||||||
|
if (u_RadiancePrefilter > 0.5)
|
||||||
|
specularIrradiance = PrefilterEnvMap(m_Params.Roughness * m_Params.Roughness, R) * u_RadiancePrefilter;
|
||||||
|
else
|
||||||
|
specularIrradiance = textureLod(u_EnvRadianceTex, RotateVectorAboutY(u_EnvMapRotation, Lr), sqrt(m_Params.Roughness) * u_EnvRadianceTexLevels).rgb * (1.0 - u_RadiancePrefilter);
|
||||||
|
|
||||||
|
// Sample BRDF Lut, 1.0 - roughness for y-coord because texture was generated (in Sparky) for gloss model
|
||||||
|
vec2 specularBRDF = texture(u_BRDFLUTTexture, vec2(m_Params.NdotV, 1.0 - m_Params.Roughness)).rg;
|
||||||
|
vec3 specularIBL = specularIrradiance * (F * specularBRDF.x + specularBRDF.y);
|
||||||
|
|
||||||
|
return kd * diffuseIBL + specularIBL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
// Standard PBR inputs
|
||||||
|
m_Params.Albedo = u_AlbedoTexToggle > 0.5 ? texture(u_AlbedoTexture, vs_Input.TexCoord).rgb : u_AlbedoColor;
|
||||||
|
m_Params.Metalness = u_MetalnessTexToggle > 0.5 ? texture(u_MetalnessTexture, vs_Input.TexCoord).r : u_Metalness;
|
||||||
|
m_Params.Roughness = u_RoughnessTexToggle > 0.5 ? texture(u_RoughnessTexture, vs_Input.TexCoord).r : u_Roughness;
|
||||||
|
m_Params.Roughness = max(m_Params.Roughness, 0.05); // Minimum roughness of 0.05 to keep specular highlight
|
||||||
|
|
||||||
|
// Normals (either from vertex or map)
|
||||||
|
m_Params.Normal = normalize(vs_Input.Normal);
|
||||||
|
if (u_NormalTexToggle > 0.5)
|
||||||
|
{
|
||||||
|
m_Params.Normal = normalize(2.0 * texture(u_NormalTexture, vs_Input.TexCoord).rgb - 1.0);
|
||||||
|
m_Params.Normal = normalize(vs_Input.WorldNormals * m_Params.Normal);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_Params.View = normalize(u_CameraPosition - vs_Input.WorldPosition);
|
||||||
|
m_Params.NdotV = max(dot(m_Params.Normal, m_Params.View), 0.0);
|
||||||
|
|
||||||
|
// Specular reflection vector
|
||||||
|
vec3 Lr = 2.0 * m_Params.NdotV * m_Params.Normal - m_Params.View;
|
||||||
|
|
||||||
|
// Fresnel reflectance, metals use albedo
|
||||||
|
vec3 F0 = mix(Fdielectric, m_Params.Albedo, m_Params.Metalness);
|
||||||
|
|
||||||
|
vec3 lightContribution = Lighting(F0);
|
||||||
|
vec3 iblContribution = IBL(F0, Lr);
|
||||||
|
|
||||||
|
color = vec4(lightContribution + iblContribution, 1.0);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user