add RHI, replace Renderer3D code using RHI function, now a little bug is that the selected entity with incorrect outline render
This commit is contained in:
426
Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp
Normal file
426
Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.cpp
Normal file
@ -0,0 +1,426 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#include "OpenGLCommandBuffer.h"
|
||||
|
||||
#include "Prism/Renderer/Texture.h"
|
||||
#include "Prism/Renderer/StorageBuffer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
GLenum OpenGLCommandBuffer::MapCompareOp(const CompareOp Option)
|
||||
{
|
||||
switch (Option) {
|
||||
case CompareOp::Never: return GL_NEVER;
|
||||
case CompareOp::Less: return GL_LESS;
|
||||
case CompareOp::Equal: return GL_EQUAL;
|
||||
case CompareOp::LessEqual: return GL_LEQUAL;
|
||||
case CompareOp::Greater: return GL_GREATER;
|
||||
case CompareOp::NotEqual: return GL_NOTEQUAL;
|
||||
case CompareOp::GreaterEqual: return GL_GEQUAL;
|
||||
case CompareOp::Always: return GL_ALWAYS;
|
||||
}
|
||||
return GL_ALWAYS;
|
||||
}
|
||||
|
||||
GLenum OpenGLCommandBuffer::MapStencilOp(const StencilOp Option)
|
||||
{
|
||||
switch (Option) {
|
||||
case StencilOp::Keep: return GL_KEEP;
|
||||
case StencilOp::Zero: return GL_ZERO;
|
||||
case StencilOp::Replace: return GL_REPLACE;
|
||||
case StencilOp::Incr: return GL_INCR;
|
||||
case StencilOp::Decr: return GL_DECR;
|
||||
case StencilOp::Invert: return GL_INVERT;
|
||||
case StencilOp::IncrWrap: return GL_INCR_WRAP;
|
||||
case StencilOp::DecrWrap: return GL_DECR_WRAP;
|
||||
}
|
||||
return GL_KEEP;
|
||||
}
|
||||
|
||||
GLenum OpenGLCommandBuffer::MapCullMode(CullMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case CullMode::None: return GL_NONE;
|
||||
case CullMode::Front: return GL_FRONT;
|
||||
case CullMode::Back: return GL_BACK;
|
||||
}
|
||||
return GL_BACK;
|
||||
}
|
||||
|
||||
GLenum OpenGLCommandBuffer::MapPolygonMode(PolygonMode mode)
|
||||
{
|
||||
switch (mode) {
|
||||
case PolygonMode::Fill: return GL_FILL;
|
||||
case PolygonMode::Line: return GL_LINE;
|
||||
case PolygonMode::Point: return GL_POINT;
|
||||
}
|
||||
return GL_FILL;
|
||||
}
|
||||
|
||||
GLenum OpenGLCommandBuffer::MapPrimitiveType(PrimitiveType type)
|
||||
{
|
||||
switch (type) {
|
||||
case PrimitiveType::Triangles: return GL_TRIANGLES;
|
||||
case PrimitiveType::Lines: return GL_LINES;
|
||||
case PrimitiveType::Points: return GL_POINTS;
|
||||
}
|
||||
return GL_TRIANGLES;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetViewport(const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height) const
|
||||
{
|
||||
glViewport(x, y, width, height);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetScissor(const uint32_t x, const uint32_t y, const uint32_t width, const uint32_t height) const
|
||||
{
|
||||
glScissor(x, y, width, height);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetDepthTest(const bool enable) const
|
||||
{
|
||||
if (enable) glEnable(GL_DEPTH_TEST);
|
||||
else glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetDepthFunc(const CompareOp func) const
|
||||
{
|
||||
glDepthFunc(MapCompareOp(func));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetStencilTest(const bool enable) const
|
||||
{
|
||||
if (enable) glEnable(GL_STENCIL_TEST);
|
||||
else glDisable(GL_STENCIL_TEST);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetStencilOp(const StencilOp fail, const StencilOp zFail, const StencilOp zPass) const
|
||||
{
|
||||
glStencilOp(MapStencilOp(fail), MapStencilOp(zFail), MapStencilOp(zPass));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetStencilMask(uint32_t mask) const
|
||||
{
|
||||
glStencilMask(mask);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetCullMode(CullMode mode) const
|
||||
{
|
||||
if (mode == CullMode::None) glDisable(GL_CULL_FACE);
|
||||
else {
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(MapCullMode(mode));
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetPolygonMode(PolygonMode mode) const
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, MapPolygonMode(mode));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetLineWidth(const float width) const
|
||||
{
|
||||
glLineWidth(width);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetLineThickness(const float thickness) const
|
||||
{
|
||||
glLineWidth(thickness);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetPointSize(float size) const
|
||||
{
|
||||
glPointSize(size);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindFramebuffer(const RendererID rendererId) const
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, rendererId);
|
||||
}
|
||||
|
||||
GLuint FramebufferTargetToOpenGL(const FramebufferTarget target)
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case FramebufferTarget::Draw: return GL_DRAW_FRAMEBUFFER;
|
||||
case FramebufferTarget::Read: return GL_READ_FRAMEBUFFER;
|
||||
case FramebufferTarget::Both: return GL_FRAMEBUFFER;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindFramebuffer(const FramebufferTarget target, const RendererID rendererId) const
|
||||
{
|
||||
glBindFramebuffer(FramebufferTargetToOpenGL(target), rendererId);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindTexture(const uint32_t slot, const uint32_t textureID) const
|
||||
{
|
||||
glBindTextureUnit(slot, textureID);
|
||||
}
|
||||
|
||||
static GLenum MapAccessMode(AccessMode mode) {
|
||||
switch (mode) {
|
||||
case AccessMode::ReadOnly: return GL_READ_ONLY;
|
||||
case AccessMode::WriteOnly: return GL_WRITE_ONLY;
|
||||
case AccessMode::ReadWrite: return GL_READ_WRITE;
|
||||
}
|
||||
return GL_READ_WRITE;
|
||||
}
|
||||
|
||||
static GLenum MapTextureFormat(TextureFormat format) {
|
||||
switch (format)
|
||||
{
|
||||
case TextureFormat::RGB: return GL_RGB8;
|
||||
case TextureFormat::RGBA: return GL_RGBA8;
|
||||
case TextureFormat::RGBA16F: return GL_RGBA16F;
|
||||
}
|
||||
return GL_RGBA8;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const
|
||||
{
|
||||
const GLenum glAccess = MapAccessMode(access); // 将 AccessMode 转为 GL_READ_ONLY, GL_WRITE_ONLY, GL_READ_WRITE
|
||||
const GLenum glFormat = MapTextureFormat(format); // 将 TextureFormat 转为 GL_RGBA16F 等内部格式
|
||||
glBindImageTexture(unit, textureID, level, layered ? GL_TRUE : GL_FALSE, layer, glAccess, glFormat);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindTextureUnit(uint32_t i, RendererID rendererId) const
|
||||
{
|
||||
glBindTextureUnit(i, rendererId);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindSampler(uint32_t slot, uint32_t samplerID) const
|
||||
{
|
||||
glBindSampler(slot, samplerID);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetDrawBuffer(const uint32_t attachment) const
|
||||
{
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0 + attachment);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetReadBuffer(const uint32_t attachment) const
|
||||
{
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0 + attachment);
|
||||
}
|
||||
|
||||
GLuint BufferFormatToOpenGL(const BufferFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case BufferFormat::R32UI: return GL_R32UI;
|
||||
case BufferFormat::RGB16F: return GL_RGB16F;
|
||||
}
|
||||
return GL_RGB16F;
|
||||
}
|
||||
|
||||
GLuint PixelFormatToOpenGL(const PixelFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
case PixelFormat::RED: return GL_RED;
|
||||
case PixelFormat::RGBA: return GL_RGBA;
|
||||
}
|
||||
return GL_RGBA;
|
||||
}
|
||||
|
||||
GLuint DataTypeToOpenGL(const DataType type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DataType::UnsignedInt: return GL_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
return GL_UNSIGNED_INT;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::ClearBufferData(Ref<StorageBuffer> buffer, BufferFormat internalFormat,
|
||||
PixelFormat format, DataType type, const void* data) const
|
||||
{
|
||||
glClearNamedBufferData(buffer->GetRendererID(), BufferFormatToOpenGL(internalFormat), PixelFormatToOpenGL(format), DataTypeToOpenGL(type), data);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::GenerateMipmap(const uint32_t textureID) const
|
||||
{
|
||||
glGenerateTextureMipmap(textureID);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, const bool faceCulling) const
|
||||
{
|
||||
if (!depthTest)
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
GLenum glPrimitiveType = 0;
|
||||
switch (type)
|
||||
{
|
||||
case PrimitiveType::Triangles:
|
||||
glPrimitiveType = GL_TRIANGLES;
|
||||
break;
|
||||
case PrimitiveType::Lines:
|
||||
glPrimitiveType = GL_LINES;
|
||||
break;
|
||||
case PrimitiveType::Points:
|
||||
break;
|
||||
}
|
||||
|
||||
if (faceCulling)
|
||||
glEnable(GL_CULL_FACE);
|
||||
else
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
glDrawElements(glPrimitiveType, count, GL_UNSIGNED_INT, nullptr);
|
||||
|
||||
if (!depthTest)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::DrawIndexed(const PrimitiveType type, const uint32_t indexCount, const uint32_t instanceCount, const uint32_t firstIndex, const int32_t vertexOffset, uint32_t firstInstance) const
|
||||
{
|
||||
const GLenum glType = MapPrimitiveType(type);
|
||||
|
||||
const void* offset = (void*)(firstIndex * sizeof(uint32_t));
|
||||
glDrawElementsInstancedBaseVertex(glType, indexCount, GL_UNSIGNED_INT, offset, instanceCount, vertexOffset);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex,
|
||||
uint32_t firstInstance) const
|
||||
{
|
||||
glDrawArraysInstancedBaseInstance(MapPrimitiveType(type), firstVertex, vertexCount, instanceCount, firstInstance);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const
|
||||
{
|
||||
glDispatchCompute(groupX, groupY, groupZ);
|
||||
}
|
||||
|
||||
|
||||
GLuint MemoryBarrierMaskToOpenGLFormat(MemoryBarrierMask barrier)
|
||||
{
|
||||
switch (barrier)
|
||||
{
|
||||
case MemoryBarrierMask::VertexAttribArray: return GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
|
||||
case MemoryBarrierMask::ElementArray: return GL_ELEMENT_ARRAY_BARRIER_BIT;
|
||||
case MemoryBarrierMask::Uniform: return GL_UNIFORM_BARRIER_BIT;
|
||||
case MemoryBarrierMask::TextureFetch: return GL_TEXTURE_FETCH_BARRIER_BIT;
|
||||
case MemoryBarrierMask::ShaderImageAccess: return GL_SHADER_IMAGE_ACCESS_BARRIER_BIT;
|
||||
case MemoryBarrierMask::Command: return GL_COMMAND_BARRIER_BIT;
|
||||
case MemoryBarrierMask::PixelBuffer: return GL_PIXEL_BUFFER_BARRIER_BIT;
|
||||
case MemoryBarrierMask::TextureUpdate: return GL_TEXTURE_UPDATE_BARRIER_BIT;
|
||||
case MemoryBarrierMask::BufferUpdate: return GL_BUFFER_UPDATE_BARRIER_BIT;
|
||||
case MemoryBarrierMask::Framebuffer: return GL_FRAMEBUFFER_BARRIER_BIT;
|
||||
case MemoryBarrierMask::TransformFeedback: return GL_TRANSFORM_FEEDBACK_BARRIER_BIT;
|
||||
case MemoryBarrierMask::AtomicCounter: return GL_ATOMIC_COUNTER_BARRIER_BIT;
|
||||
case MemoryBarrierMask::ShaderStorage: return GL_SHADER_STORAGE_BARRIER_BIT;
|
||||
case MemoryBarrierMask::None: return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void OpenGLCommandBuffer::MemoryBarrier(const MemoryBarrierMask barriers) const
|
||||
{
|
||||
glMemoryBarrier(MemoryBarrierMaskToOpenGLFormat(barriers));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::Clear(const glm::vec4& color, bool clearColor, bool clearDepth) const
|
||||
{
|
||||
GLbitfield mask = 0;
|
||||
if (clearColor) {
|
||||
glClearColor(color.r, color.g, color.b, color.a);
|
||||
mask |= GL_COLOR_BUFFER_BIT;
|
||||
}
|
||||
if (clearDepth) mask |= GL_DEPTH_BUFFER_BIT;
|
||||
glClear(mask);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetStencilFunc(const CompareOp compare, const uint32_t ref, const uint32_t mask) const
|
||||
{
|
||||
glStencilFunc(MapCompareOp(compare), ref, mask);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetLineSmooth(const bool enable) const
|
||||
{
|
||||
if (enable) glEnable(GL_LINE_SMOOTH);
|
||||
else glDisable(GL_LINE_SMOOTH);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::SetDepthWrite(const bool enable) const
|
||||
{
|
||||
glDepthMask(enable ? GL_TRUE : GL_FALSE);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel,
|
||||
uint32_t dstLevel, uint32_t srcX, uint32_t srcY, uint32_t srcZ, uint32_t dstX, uint32_t dstY, uint32_t dstZ,
|
||||
uint32_t width, uint32_t height, uint32_t depth) const
|
||||
{
|
||||
glCopyImageSubData(srcTexture, GL_TEXTURE_CUBE_MAP, srcLevel, srcX, srcY, srcZ,
|
||||
dstTexture, GL_TEXTURE_CUBE_MAP, dstLevel, dstX, dstY, dstZ,
|
||||
width, height, depth);
|
||||
}
|
||||
|
||||
int32_t OpenGLCommandBuffer::GetUniformLocation(const uint32_t program, const std::string& name) const {
|
||||
return glGetUniformLocation(program, name.c_str());
|
||||
}
|
||||
|
||||
GLuint BlitMaskToOpenGL(BlitMask mask)
|
||||
{
|
||||
switch (mask) {
|
||||
case BlitMask::Color: return GL_COLOR_BUFFER_BIT;
|
||||
case BlitMask::Depth: return GL_DEPTH_BUFFER_BIT;
|
||||
case BlitMask::Stencila: return GL_STENCIL_BUFFER_BIT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
GLuint BlitFilterToOpenGL(BlitFilter filter)
|
||||
{
|
||||
switch (filter) {
|
||||
case BlitFilter::Nearest: return GL_NEAREST;
|
||||
case BlitFilter::Linear: return GL_LINEAR;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1, int32_t dstX0,
|
||||
int32_t dstY0, int32_t dstX1, int32_t dstY1, BlitMask mask, BlitFilter filter) const
|
||||
{
|
||||
glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, BlitMaskToOpenGL(mask), BlitFilterToOpenGL(filter));
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::ProgramUniform1f(const uint32_t program, const int32_t location, const float value) const
|
||||
{
|
||||
glProgramUniform1f(program, location, value);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::UseProgram(const uint32_t programID) const
|
||||
{
|
||||
glUseProgram(programID);
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::BindStorageBuffer(const uint32_t binding, const Ref<StorageBuffer>& ref) const
|
||||
{
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, binding, ref->GetRendererID());
|
||||
}
|
||||
|
||||
void OpenGLCommandBuffer::ResolveMultisampleTexture(const Ref<FrameBuffer>& src, const Ref<Texture>& dst) const
|
||||
{
|
||||
uint32_t resolveFBO;
|
||||
glGenFramebuffers(1, &resolveFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dst->GetRendererID(), 0);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, src->GetRendererID());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBlitFramebuffer(0, 0, src->GetWidth(), src->GetHeight(),
|
||||
0, 0, src->GetWidth(), src->GetHeight(),
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
glDeleteFramebuffers(1, &resolveFBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
}
|
||||
}
|
||||
97
Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h
Normal file
97
Prism/src/Prism/Platform/OpenGL/OpenGLCommandBuffer.h
Normal file
@ -0,0 +1,97 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#ifndef PRISM_OPENGLCOMMANDBUFFER_H
|
||||
#define PRISM_OPENGLCOMMANDBUFFER_H
|
||||
#include "OpenGLRenderPass.h"
|
||||
#include "glad/glad.h"
|
||||
#include "Prism/Renderer/RHI/RHICommandBuffer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
enum class TextureFormat;
|
||||
|
||||
class OpenGLCommandBuffer : public RHICommandBuffer
|
||||
{
|
||||
public:
|
||||
static GLenum MapCompareOp(CompareOp op);
|
||||
|
||||
static GLenum MapStencilOp(StencilOp op);
|
||||
|
||||
static GLenum MapCullMode(CullMode mode);
|
||||
|
||||
static GLenum MapPolygonMode(PolygonMode mode);
|
||||
|
||||
static GLenum MapPrimitiveType(PrimitiveType type);
|
||||
|
||||
void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const override;
|
||||
|
||||
void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const override;
|
||||
|
||||
void SetDepthTest(bool enable) const override;
|
||||
|
||||
void SetDepthFunc(CompareOp func) const override;
|
||||
|
||||
void SetStencilTest(bool enable) const override;
|
||||
|
||||
void SetStencilOp(StencilOp fail, StencilOp zFail, StencilOp zPass) const override;
|
||||
|
||||
void SetStencilMask(uint32_t mask) const override;
|
||||
|
||||
void SetCullMode(CullMode mode) const override;
|
||||
|
||||
void SetPolygonMode(PolygonMode mode) const override;
|
||||
|
||||
void SetLineWidth(float width) const override;
|
||||
void SetLineThickness(float thickness) const override;
|
||||
|
||||
void SetPointSize(float size) const override;
|
||||
|
||||
void BindFramebuffer(RendererID rendererId) const override;
|
||||
void BindFramebuffer(FramebufferTarget target, RendererID rendererId) const override;
|
||||
void BindTexture(uint32_t slot, uint32_t textureID) const override;
|
||||
void BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const override;
|
||||
void BindTextureUnit(uint32_t i, RendererID rendererId) const override;
|
||||
void BindSampler(uint32_t slot, uint32_t samplerID) const override;
|
||||
|
||||
void SetDrawBuffer(uint32_t attachment) const override;
|
||||
void SetReadBuffer(uint32_t attachment) const override;
|
||||
|
||||
void ClearBufferData(Ref<StorageBuffer> buffer, BufferFormat internalFormat, PixelFormat format, DataType type, const void* data) const override;
|
||||
|
||||
void GenerateMipmap(uint32_t textureID) const override;
|
||||
|
||||
|
||||
void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling) const override;
|
||||
|
||||
void DrawIndexed(PrimitiveType type, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) const override;
|
||||
|
||||
void Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex, uint32_t firstInstance) const override;
|
||||
|
||||
void DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const override;
|
||||
|
||||
void MemoryBarrier(MemoryBarrierMask barriers) const override;
|
||||
|
||||
void Clear(const glm::vec4& color, bool clearColor, bool clearDepth) const override;
|
||||
void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const override;
|
||||
void SetLineSmooth(bool enable) const override;
|
||||
void SetDepthWrite(bool enable) const override;
|
||||
|
||||
void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture, uint32_t srcLevel, uint32_t dstLevel, uint32_t srcX, uint32_t srcY, uint32_t srcZ, uint32_t dstX, uint32_t dstY, uint32_t dstZ, uint32_t width, uint32_t height, uint32_t depth) const override;
|
||||
int32_t GetUniformLocation(uint32_t program, const std::string& name) const override;
|
||||
void BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1, int32_t dstX0, int32_t dstY0, int32_t dstX1, int32_t dstY1, BlitMask mask, BlitFilter filter) const override;
|
||||
|
||||
void ProgramUniform1f(uint32_t program, int32_t location, float value) const override;
|
||||
|
||||
void UseProgram(uint32_t programID) const override;
|
||||
|
||||
void BindStorageBuffer(uint32_t binding, const Ref<StorageBuffer>& ref) const override;
|
||||
|
||||
void ResolveMultisampleTexture(const Ref<FrameBuffer>& src, const Ref<Texture>& dst) const override;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_OPENGLCOMMANDBUFFER_H
|
||||
87
Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.cpp
Normal file
87
Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.cpp
Normal file
@ -0,0 +1,87 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#include "OpenGLRHIDevice.h"
|
||||
|
||||
#include "OpenGLCommandBuffer.h"
|
||||
#include "glm/gtc/type_ptr.hpp"
|
||||
|
||||
#include "Prism/Renderer/RendererAPI.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
static GLenum MapFilterMode(FilterMode mode) {
|
||||
switch (mode) {
|
||||
case FilterMode::Nearest: return GL_NEAREST;
|
||||
case FilterMode::Linear: return GL_LINEAR;
|
||||
case FilterMode::NearestMipmapNearest: return GL_NEAREST_MIPMAP_NEAREST;
|
||||
case FilterMode::LinearMipmapNearest: return GL_LINEAR_MIPMAP_NEAREST;
|
||||
case FilterMode::NearestMipmapLinear: return GL_NEAREST_MIPMAP_LINEAR;
|
||||
case FilterMode::LinearMipmapLinear: return GL_LINEAR_MIPMAP_LINEAR;
|
||||
default: return GL_LINEAR;
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum MapWrapMode(WrapMode mode) {
|
||||
switch (mode) {
|
||||
case WrapMode::Repeat: return GL_REPEAT;
|
||||
case WrapMode::MirroredRepeat: return GL_MIRRORED_REPEAT;
|
||||
case WrapMode::ClampToEdge: return GL_CLAMP_TO_EDGE;
|
||||
case WrapMode::ClampToBorder: return GL_CLAMP_TO_BORDER;
|
||||
case WrapMode::MirrorClampToEdge: return GL_MIRROR_CLAMP_TO_EDGE;
|
||||
default: return GL_REPEAT;
|
||||
}
|
||||
}
|
||||
|
||||
static GLenum MapCompareFunc(CompareFunc func) {
|
||||
switch (func) {
|
||||
case CompareFunc::Never: return GL_NEVER;
|
||||
case CompareFunc::Less: return GL_LESS;
|
||||
case CompareFunc::Equal: return GL_EQUAL;
|
||||
case CompareFunc::LessEqual: return GL_LEQUAL;
|
||||
case CompareFunc::Greater: return GL_GREATER;
|
||||
case CompareFunc::NotEqual: return GL_NOTEQUAL;
|
||||
case CompareFunc::GreaterEqual: return GL_GEQUAL;
|
||||
case CompareFunc::Always: return GL_ALWAYS;
|
||||
default: return GL_ALWAYS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Ref<RHICommandBuffer> OpenGLRHIDevice::CreateCommandBuffer()
|
||||
{
|
||||
return Ref<OpenGLCommandBuffer>::Create();
|
||||
}
|
||||
|
||||
RendererID OpenGLRHIDevice::CreateSampler(const SamplerDesc& desc)
|
||||
{
|
||||
GLuint sampler;
|
||||
glGenSamplers(1, &sampler);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, MapFilterMode(desc.MinFilter));
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, MapFilterMode(desc.MagFilter));
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, MapWrapMode(desc.WrapU));
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, MapWrapMode(desc.WrapV));
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, MapWrapMode(desc.WrapW));
|
||||
if (desc.MaxAnisotropy > 1.0f) {
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY, desc.MaxAnisotropy);
|
||||
}
|
||||
glSamplerParameterf(sampler, GL_TEXTURE_LOD_BIAS, desc.MipLodBias);
|
||||
if (desc.EnableCompare) {
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, MapCompareFunc(desc.CompareFunc));
|
||||
} else {
|
||||
glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE);
|
||||
}
|
||||
if (desc.WrapU == WrapMode::ClampToBorder || desc.WrapV == WrapMode::ClampToBorder || desc.WrapW == WrapMode::ClampToBorder) {
|
||||
glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR, glm::value_ptr(desc.BorderColor));
|
||||
}
|
||||
return sampler;
|
||||
}
|
||||
|
||||
void OpenGLRHIDevice::DestroySampler(const RendererID sampler)
|
||||
{
|
||||
glDeleteSamplers(1, &sampler);
|
||||
}
|
||||
}
|
||||
22
Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.h
Normal file
22
Prism/src/Prism/Platform/OpenGL/OpenGLRHIDevice.h
Normal file
@ -0,0 +1,22 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#ifndef PRISM_OPENGLRHIDEVICE_H
|
||||
#define PRISM_OPENGLRHIDEVICE_H
|
||||
#include "Prism/Renderer/RHI/RHIDevice.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class OpenGLRHIDevice : public RHIDevice
|
||||
{
|
||||
public:
|
||||
Ref<RHICommandBuffer> CreateCommandBuffer() override;
|
||||
|
||||
RendererID CreateSampler(const SamplerDesc& desc) override;
|
||||
void DestroySampler(RendererID sampler) override;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_OPENGLRHIDEVICE_H
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
#include "glad/glad.h"
|
||||
#include "Prism/Core/Log.h"
|
||||
#include "Prism/Renderer/RHI/RHICommandBuffer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
|
||||
5
Prism/src/Prism/Renderer/RHI/RHICommandBuffer.cpp
Normal file
5
Prism/src/Prism/Renderer/RHI/RHICommandBuffer.cpp
Normal file
@ -0,0 +1,5 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#include "RHICommandBuffer.h"
|
||||
123
Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h
Normal file
123
Prism/src/Prism/Renderer/RHI/RHICommandBuffer.h
Normal file
@ -0,0 +1,123 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#ifndef PRISM_RHICOMMANDBUFFER_H
|
||||
#define PRISM_RHICOMMANDBUFFER_H
|
||||
#include "Prism/Core/Ref.h"
|
||||
#include "Prism/Renderer/RendererAPI.h"
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace Prism {
|
||||
class FrameBuffer;
|
||||
class StorageBuffer;
|
||||
enum class TextureFormat;
|
||||
class Texture;
|
||||
class IndexBuffer;
|
||||
class VertexBuffer;
|
||||
class Pipeline;
|
||||
class RenderPass;
|
||||
|
||||
enum class CompareOp { Never, Less, Equal, LessEqual, Greater, NotEqual, GreaterEqual, Always };
|
||||
enum class StencilOp { Keep, Zero, Replace, Incr, Decr, Invert, IncrWrap, DecrWrap };
|
||||
enum class CullMode { None, Front, Back };
|
||||
enum class PolygonMode { Fill, Line, Point };
|
||||
enum class PrimitiveType { Triangles, Lines, Points };
|
||||
enum class AccessMode { ReadOnly, WriteOnly, ReadWrite };
|
||||
enum class BufferFormat { R32UI, RGB16F };
|
||||
enum class PixelFormat { RED, RGBA };
|
||||
enum class BlitFilter { Nearest, Linear };
|
||||
enum class DataType { UnsignedInt };
|
||||
enum class BlitMask { Color, Depth, Stencila };
|
||||
|
||||
enum class MemoryBarrierMask {
|
||||
None = 0,
|
||||
VertexAttribArray, // GL_VERTEX_ATTRIB_ARRAY_BARRIER_BIT
|
||||
ElementArray, // GL_ELEMENT_ARRAY_BARRIER_BIT
|
||||
Uniform, // GL_UNIFORM_BARRIER_BIT
|
||||
TextureFetch, // GL_TEXTURE_FETCH_BARRIER_BIT
|
||||
ShaderImageAccess, // GL_SHADER_IMAGE_ACCESS_BARRIER_BIT
|
||||
Command, // GL_COMMAND_BARRIER_BIT
|
||||
PixelBuffer, // GL_PIXEL_BUFFER_BARRIER_BIT
|
||||
TextureUpdate, // GL_TEXTURE_UPDATE_BARRIER_BIT
|
||||
BufferUpdate, // GL_BUFFER_UPDATE_BARRIER_BIT
|
||||
Framebuffer, // GL_FRAMEBUFFER_BARRIER_BIT
|
||||
TransformFeedback, // GL_TRANSFORM_FEEDBACK_BARRIER_BIT
|
||||
AtomicCounter, // GL_ATOMIC_COUNTER_BARRIER_BIT
|
||||
ShaderStorage, // GL_SHADER_STORAGE_BARRIER_BIT
|
||||
All // GL_ALL_BARRIER_BITS
|
||||
};
|
||||
|
||||
enum class FramebufferTarget {Read, Draw, Both};
|
||||
|
||||
class PRISM_API RHICommandBuffer : public RefCounted
|
||||
{
|
||||
public:
|
||||
virtual ~RHICommandBuffer() = default;
|
||||
|
||||
// 状态设置
|
||||
virtual void SetViewport(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const = 0;
|
||||
virtual void SetScissor(uint32_t x, uint32_t y, uint32_t width, uint32_t height) const = 0;
|
||||
virtual void SetDepthTest(bool enable) const = 0;
|
||||
virtual void SetDepthFunc(CompareOp func) const = 0;
|
||||
virtual void SetStencilTest(bool enable) const = 0;
|
||||
virtual void SetStencilOp(StencilOp fail, StencilOp zfail, StencilOp zpass) const = 0;
|
||||
virtual void SetStencilMask(uint32_t mask) const = 0;
|
||||
virtual void SetCullMode(CullMode mode) const = 0;
|
||||
virtual void SetPolygonMode(PolygonMode mode) const = 0;
|
||||
virtual void SetLineWidth(float width) const = 0;
|
||||
virtual void SetPointSize(float size) const = 0;
|
||||
virtual void SetLineThickness(float thickness) const = 0;
|
||||
|
||||
virtual void BindFramebuffer(uint32_t fbo) const = 0;
|
||||
virtual void BindFramebuffer(FramebufferTarget target, uint32_t fbo) const = 0;
|
||||
virtual void BindTexture(uint32_t slot, uint32_t textureID) const = 0;
|
||||
virtual void BindImageTexture(uint32_t unit, uint32_t textureID, int32_t level, bool layered, int32_t layer, AccessMode access, TextureFormat format) const = 0;
|
||||
virtual void BindTextureUnit(uint32_t i, RendererID rendererId) const = 0;
|
||||
virtual void BindSampler(uint32_t slot, uint32_t samplerID) const = 0;
|
||||
|
||||
virtual void SetReadBuffer(uint32_t attachment) const = 0;
|
||||
virtual void SetDrawBuffer(uint32_t attachment) const = 0;
|
||||
|
||||
virtual void ClearBufferData(Ref<StorageBuffer> buffer, BufferFormat internalFormat, PixelFormat format, DataType type, const void* data) const = 0;
|
||||
|
||||
virtual void GenerateMipmap(uint32_t textureID) const = 0;
|
||||
|
||||
// 绘制
|
||||
virtual void DrawIndexed(uint32_t count, PrimitiveType type, bool depthTest, bool faceCulling) const = 0;
|
||||
virtual void DrawIndexed(PrimitiveType type, uint32_t indexCount, uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset, uint32_t firstInstance) const = 0;
|
||||
virtual void Draw(PrimitiveType type, uint32_t vertexCount, uint32_t instanceCount,
|
||||
uint32_t firstVertex, uint32_t firstInstance) const = 0;
|
||||
|
||||
// 计算
|
||||
virtual void DispatchCompute(uint32_t groupX, uint32_t groupY, uint32_t groupZ) const = 0;
|
||||
virtual void MemoryBarrier(MemoryBarrierMask barriers) const = 0;
|
||||
|
||||
virtual void Clear(const glm::vec4& color, bool clearColor = true, bool clearDepth = true) const = 0;
|
||||
virtual void SetStencilFunc(CompareOp compare, uint32_t ref, uint32_t mask) const = 0;
|
||||
virtual void SetLineSmooth(bool enable) const = 0;
|
||||
virtual void SetDepthWrite(bool enable) const = 0;
|
||||
|
||||
virtual void CopyImageSubData(uint32_t srcTexture, uint32_t dstTexture,
|
||||
uint32_t srcLevel, uint32_t dstLevel,
|
||||
uint32_t srcX, uint32_t srcY, uint32_t srcZ,
|
||||
uint32_t dstX, uint32_t dstY, uint32_t dstZ,
|
||||
uint32_t width, uint32_t height, uint32_t depth) const = 0;
|
||||
|
||||
virtual void ProgramUniform1f(uint32_t program, int32_t location, float value) const = 0;
|
||||
virtual void BlitFramebuffer(int32_t srcX0, int32_t srcY0, int32_t srcX1, int32_t srcY1,
|
||||
int32_t dstX0, int32_t dstY0, int32_t dstX1, int32_t dstY1,
|
||||
BlitMask mask, BlitFilter filter) const = 0;
|
||||
|
||||
virtual int32_t GetUniformLocation(uint32_t program, const std::string& name) const = 0;
|
||||
|
||||
virtual void UseProgram(uint32_t programID) const = 0;
|
||||
virtual void BindStorageBuffer(uint32_t binding, const Ref<StorageBuffer>& ref) const = 0;
|
||||
|
||||
virtual void ResolveMultisampleTexture(const Ref<FrameBuffer>& src, const Ref<Texture>& dst) const = 0;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //PRISM_RHICOMMANDBUFFER_H
|
||||
23
Prism/src/Prism/Renderer/RHI/RHIDevice.cpp
Normal file
23
Prism/src/Prism/Renderer/RHI/RHIDevice.cpp
Normal file
@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#include "RHIDevice.h"
|
||||
|
||||
#include "Prism/Platform/OpenGL/OpenGLRHIDevice.h"
|
||||
#include "Prism/Renderer/RendererAPI.h"
|
||||
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
Ref<RHIDevice> RHIDevice::Create()
|
||||
{
|
||||
switch (RendererAPI::Current())
|
||||
{
|
||||
case RendererAPIType::None: return nullptr;
|
||||
case RendererAPIType::OpenGL: return Ref<OpenGLRHIDevice>::Create();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
95
Prism/src/Prism/Renderer/RHI/RHIDevice.h
Normal file
95
Prism/src/Prism/Renderer/RHI/RHIDevice.h
Normal file
@ -0,0 +1,95 @@
|
||||
//
|
||||
// Created by Atdunbg on 2026/3/31.
|
||||
//
|
||||
|
||||
#ifndef PRISM_RHIDEVICE_H
|
||||
#define PRISM_RHIDEVICE_H
|
||||
#include "Prism/Core/Ref.h"
|
||||
#include "Prism/Renderer/RendererAPI.h"
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
struct FramebufferSpecification;
|
||||
struct RenderPassSpecification;
|
||||
class RHICommandBuffer;
|
||||
class StorageBuffer;
|
||||
class RenderPass;
|
||||
class FrameBuffer;
|
||||
class Pipeline;
|
||||
class Shader;
|
||||
class Texture;
|
||||
class IndexBuffer;
|
||||
class VertexBuffer;
|
||||
|
||||
struct BufferDesc {
|
||||
uint32_t Size;
|
||||
uint32_t Usage; // GL_STATIC_DRAW, GL_DYNAMIC_DRAW, etc.
|
||||
// 对于 OpenGL,还需要 target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER)
|
||||
uint32_t Target;
|
||||
};
|
||||
|
||||
struct TextureDesc {
|
||||
uint32_t Width, Height, Depth;
|
||||
uint32_t MipLevels;
|
||||
uint32_t Format; // GL_RGBA8, GL_RGBA16F, etc.
|
||||
bool IsCubeMap = false;
|
||||
bool IsArray = false;
|
||||
uint32_t Layers = 1;
|
||||
};
|
||||
|
||||
enum class FilterMode {
|
||||
Nearest, // GL_NEAREST
|
||||
Linear, // GL_LINEAR
|
||||
NearestMipmapNearest, // GL_NEAREST_MIPMAP_NEAREST
|
||||
LinearMipmapNearest, // GL_LINEAR_MIPMAP_NEAREST
|
||||
NearestMipmapLinear, // GL_NEAREST_MIPMAP_LINEAR
|
||||
LinearMipmapLinear // GL_LINEAR_MIPMAP_LINEAR
|
||||
};
|
||||
|
||||
enum class WrapMode {
|
||||
Repeat, // GL_REPEAT
|
||||
MirroredRepeat, // GL_MIRRORED_REPEAT
|
||||
ClampToEdge, // GL_CLAMP_TO_EDGE
|
||||
ClampToBorder, // GL_CLAMP_TO_BORDER
|
||||
MirrorClampToEdge // GL_MIRROR_CLAMP_TO_EDGE (可选)
|
||||
};
|
||||
|
||||
enum class CompareFunc {
|
||||
Never, // GL_NEVER
|
||||
Less, // GL_LESS
|
||||
Equal, // GL_EQUAL
|
||||
LessEqual, // GL_LEQUAL
|
||||
Greater, // GL_GREATER
|
||||
NotEqual, // GL_NOTEQUAL
|
||||
GreaterEqual, // GL_GEQUAL
|
||||
Always // GL_ALWAYS
|
||||
};
|
||||
|
||||
struct SamplerDesc {
|
||||
FilterMode MinFilter = FilterMode::Linear; // 缩小过滤
|
||||
FilterMode MagFilter = FilterMode::Linear; // 放大过滤
|
||||
WrapMode WrapU = WrapMode::Repeat; // U 方向包裹模式
|
||||
WrapMode WrapV = WrapMode::Repeat; // V 方向包裹模式
|
||||
WrapMode WrapW = WrapMode::Repeat; // W 方向包裹模式(3D/数组纹理)
|
||||
float MaxAnisotropy = 1.0f; // 各向异性过滤(1.0 表示禁用)
|
||||
float MipLodBias = 0.0f; // Mipmap LOD 偏移
|
||||
CompareFunc CompareFunc = CompareFunc::Never; // 用于阴影比较的采样器
|
||||
bool EnableCompare = false; // 是否启用比较模式(阴影贴图)
|
||||
glm::vec4 BorderColor = glm::vec4(0.0f); // ClampToBorder 时的边界颜色
|
||||
};
|
||||
|
||||
class PRISM_API RHIDevice : public RefCounted
|
||||
{
|
||||
public:
|
||||
static Ref<RHIDevice> Create();
|
||||
|
||||
virtual ~RHIDevice() = default;
|
||||
virtual Ref<RHICommandBuffer> CreateCommandBuffer() = 0;
|
||||
virtual RendererID CreateSampler(const SamplerDesc& desc) = 0;
|
||||
virtual void DestroySampler(RendererID sampler) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#endif //PRISM_RHIDEVICE_H
|
||||
@ -9,11 +9,16 @@
|
||||
#include "RendererAPI.h"
|
||||
#include "SceneRenderer.h"
|
||||
#include "glad/glad.h"
|
||||
#include "RHI/RHICommandBuffer.h"
|
||||
#include "RHI/RHIDevice.h"
|
||||
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
RendererAPIType RendererAPI::s_CurrentRendererAPI = RendererAPIType::OpenGL;
|
||||
Ref<RHIDevice> Renderer::s_Device;
|
||||
Ref<RHICommandBuffer> Renderer::s_CommandBuffer;
|
||||
|
||||
|
||||
struct RendererData
|
||||
{
|
||||
@ -30,6 +35,9 @@ namespace Prism
|
||||
|
||||
void Renderer::Init()
|
||||
{
|
||||
s_Device = RHIDevice::Create();
|
||||
s_CommandBuffer = s_Device->CreateCommandBuffer();
|
||||
|
||||
s_Data.m_ShaderLibrary = Ref<ShaderLibrary>::Create();
|
||||
Submit([](){ RendererAPI::Init(); });
|
||||
|
||||
@ -62,18 +70,30 @@ namespace Prism
|
||||
s_Data.m_FullscreenQuadIndexBuffer = IndexBuffer::Create(fullScreenQuadIndices, sizeof(fullScreenQuadIndices[0]) * sizeof(fullScreenQuadIndices));
|
||||
}
|
||||
|
||||
Ref<RHICommandBuffer> Renderer::GetCommandBuffer()
|
||||
{
|
||||
return s_CommandBuffer;
|
||||
}
|
||||
|
||||
Ref<RHIDevice> Renderer::GetDevice()
|
||||
{
|
||||
return s_Device;
|
||||
}
|
||||
|
||||
void Renderer::Clear()
|
||||
{
|
||||
Submit([]()
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd]()
|
||||
{
|
||||
RendererAPI::Clear(0.0f, 0.0f, 0.0f, 1.0f);
|
||||
cmd->Clear({0.0f, 0.0f, 0.0f, 1.0f});
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::Clear(float r, float g, float b, float a)
|
||||
{
|
||||
Submit([=](){
|
||||
RendererAPI::Clear(r, g, b, a);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([r, g, b, a, cmd](){
|
||||
cmd->Clear({r, g, b, a});
|
||||
});
|
||||
}
|
||||
|
||||
@ -90,15 +110,18 @@ namespace Prism
|
||||
|
||||
void Renderer::DrawIndexed(const uint32_t count, const PrimitiveType type, const bool depthTest, bool cullFace)
|
||||
{
|
||||
Submit([=]() {
|
||||
RendererAPI::DrawIndexed(count, type, depthTest, cullFace);
|
||||
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, count, type, depthTest, cullFace]() {
|
||||
cmd->DrawIndexed(count, type, depthTest, cullFace);
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::SetLineThickness(const float thickness)
|
||||
{
|
||||
Submit([=]() {
|
||||
RendererAPI::SetLineThickness(thickness);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, thickness]() {
|
||||
cmd->SetLineThickness(thickness);
|
||||
});
|
||||
}
|
||||
|
||||
@ -116,19 +139,25 @@ namespace Prism
|
||||
|
||||
renderPass->GetSpecification().TargetFramebuffer->Bind();
|
||||
|
||||
if (clear)
|
||||
{
|
||||
const glm::vec4& clearColor = renderPass->GetSpecification().TargetFramebuffer->GetSpecification().ClearColor;
|
||||
Submit([=]() {
|
||||
RendererAPI::Clear(clearColor.r, clearColor.g, clearColor.b, clearColor.a);
|
||||
});
|
||||
}
|
||||
auto cmd = s_CommandBuffer;
|
||||
auto fb = renderPass->GetSpecification().TargetFramebuffer;
|
||||
Submit([cmd, fb, clear]() {
|
||||
cmd->BindFramebuffer(fb->GetRendererID());
|
||||
if (clear)
|
||||
{
|
||||
const glm::vec4& clearColor = fb->GetSpecification().ClearColor;
|
||||
cmd->Clear(clearColor, true, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::EndRenderPass()
|
||||
{
|
||||
PM_CORE_ASSERT(s_Data.m_ActiveRenderPass, "No active render pass! Have you called Renderer::EndRenderPass twice?");
|
||||
s_Data.m_ActiveRenderPass->GetSpecification().TargetFramebuffer->Unbind();
|
||||
PM_CORE_ASSERT(s_Data.m_ActiveRenderPass, "No active render pass!");
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd]() {
|
||||
cmd->BindFramebuffer(0);
|
||||
});
|
||||
s_Data.m_ActiveRenderPass = nullptr;
|
||||
}
|
||||
|
||||
@ -169,7 +198,7 @@ namespace Prism
|
||||
s_Data.m_FullscreenQuadPipeline->Bind();
|
||||
s_Data.m_FullscreenQuadIndexBuffer->Bind();
|
||||
|
||||
Renderer::DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
|
||||
DrawIndexed(6, PrimitiveType::Triangles, depthTest, cullFace);
|
||||
}
|
||||
|
||||
void Renderer::SubmitMesh(Ref<Mesh>& mesh, const glm::mat4& transform, const std::vector<Ref<MaterialInstance>>& overrideMaterials)
|
||||
@ -201,22 +230,15 @@ namespace Prism
|
||||
}
|
||||
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||
|
||||
Renderer::Submit([submesh, material]() {
|
||||
if (material->GetFlag(MaterialFlag::DepthTest))
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
}
|
||||
else
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, submesh, material]() {
|
||||
// 状态设置通过 cmd
|
||||
cmd->SetDepthTest(material->GetFlag(MaterialFlag::DepthTest));
|
||||
cmd->SetDepthFunc(CompareOp::LessEqual); // 对应 GL_LEQUAL
|
||||
cmd->SetCullMode(material->GetFlag(MaterialFlag::TwoSided) ? CullMode::None : CullMode::Back);
|
||||
|
||||
if (!material->GetFlag(MaterialFlag::TwoSided))
|
||||
glEnable(GL_CULL_FACE);
|
||||
else
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||
// 绘制
|
||||
cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -250,22 +272,12 @@ namespace Prism
|
||||
}
|
||||
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||
|
||||
Renderer::Submit([submesh, material]() {
|
||||
if (material->GetFlag(MaterialFlag::DepthTest))
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
}
|
||||
else
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
|
||||
if (!material->GetFlag(MaterialFlag::TwoSided))
|
||||
glEnable(GL_CULL_FACE);
|
||||
else
|
||||
glDisable(GL_CULL_FACE);
|
||||
|
||||
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, submesh, material]() {
|
||||
cmd->SetDepthTest(material->GetFlag(MaterialFlag::DepthTest));
|
||||
cmd->SetDepthFunc(CompareOp::LessEqual);
|
||||
cmd->SetCullMode(material->GetFlag(MaterialFlag::TwoSided) ? CullMode::None : CullMode::Back);
|
||||
cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -289,8 +301,9 @@ namespace Prism
|
||||
}
|
||||
shader->SetMat4("u_Transform", transform * submesh.Transform);
|
||||
|
||||
Submit([submesh]() {
|
||||
glDrawElementsBaseVertex(GL_TRIANGLES, submesh.IndexCount, GL_UNSIGNED_INT, (void*)(sizeof(uint32_t) * submesh.BaseIndex), submesh.BaseVertex);
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([cmd, submesh]() {
|
||||
cmd->DrawIndexed(PrimitiveType::Triangles, submesh.IndexCount, 1, submesh.BaseIndex, submesh.BaseVertex, 0);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -335,19 +348,14 @@ namespace Prism
|
||||
|
||||
void Renderer::DispatchCompute(int x, int y, int z)
|
||||
{
|
||||
Submit([x, y, z]()
|
||||
auto cmd = s_CommandBuffer;
|
||||
Submit([x, y, z, cmd]()
|
||||
{
|
||||
RendererAPI::DispatchCompute(x, y, z);
|
||||
cmd->DispatchCompute(x, y, z);
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer::MemoryBarrier(int barrier)
|
||||
{
|
||||
Submit([barrier]()
|
||||
{
|
||||
RendererAPI::MemoryBarrier(barrier);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
RenderCommandQueue& Renderer::GetRenderCommandQueue()
|
||||
{
|
||||
|
||||
@ -13,12 +13,19 @@
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
class PRISM_API Renderer
|
||||
enum class PrimitiveType;
|
||||
class RHICommandBuffer;
|
||||
class RHIDevice;
|
||||
|
||||
class PRISM_API Renderer
|
||||
{
|
||||
public:
|
||||
typedef void(*RenderCommandFn)(void*);
|
||||
static void Init();
|
||||
|
||||
static Ref<RHICommandBuffer> GetCommandBuffer();
|
||||
static Ref<RHIDevice> GetDevice();
|
||||
|
||||
static void Clear();
|
||||
static void Clear(float r, float g, float b, float a = 1.0f);
|
||||
static void SetClearColor(float r, float g, float b, float a);
|
||||
@ -61,10 +68,12 @@ namespace Prism
|
||||
static void DrawAABB(const AABB& aabb, const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f));
|
||||
static void DrawAABB(const Ref<Mesh>& mesh,const glm::mat4& transform, const glm::vec4& color = glm::vec4(1.0f));
|
||||
static void DispatchCompute(int x, int y, int z);
|
||||
static void MemoryBarrier(int barrier);
|
||||
|
||||
private:
|
||||
static RenderCommandQueue& GetRenderCommandQueue();
|
||||
|
||||
static Ref<RHIDevice> s_Device;
|
||||
static Ref<RHICommandBuffer> s_CommandBuffer;
|
||||
};
|
||||
|
||||
#if 0
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
#include "Renderer.h"
|
||||
#include "Shader.h"
|
||||
#include "VertexArray.h"
|
||||
#include "RHI/RHICommandBuffer.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
|
||||
@ -6,13 +6,15 @@
|
||||
|
||||
#include "Prism/Core/Timer.h"
|
||||
#include "Prism/Scene/Scene.h"
|
||||
#include <glad/glad.h>
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "Renderer2D.h"
|
||||
#include "SceneRenderer.h"
|
||||
#include "StorageBuffer.h"
|
||||
#include "glad/glad.h"
|
||||
#include "Prism/Scene/Components.h"
|
||||
#include "RHI/RHICommandBuffer.h"
|
||||
#include "RHI/RHIDevice.h"
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
@ -225,16 +227,14 @@ namespace Prism
|
||||
shadowMapRenderPassSpec.TargetFramebuffer = FrameBuffer::Create(shadowMapFramebufferSpec);
|
||||
s_Data.ShadowMapRenderPass = RenderPass::Create(shadowMapRenderPassSpec);
|
||||
|
||||
Renderer::Submit([]()
|
||||
{
|
||||
glGenSamplers(1, &s_Data.ShadowMapSampler);
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
|
||||
// Setup the shadowMap depth sampler
|
||||
glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glSamplerParameteri(s_Data.ShadowMapSampler, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
});
|
||||
SamplerDesc desc;
|
||||
desc.MinFilter = FilterMode::Linear;
|
||||
desc.MagFilter = FilterMode::Linear;
|
||||
desc.WrapU = WrapMode::ClampToEdge;
|
||||
desc.WrapV = WrapMode::ClampToEdge;
|
||||
s_Data.ShadowMapSampler = Renderer::GetDevice()->CreateSampler(desc);
|
||||
}
|
||||
/////////////////////////////////////////////
|
||||
|
||||
@ -340,6 +340,8 @@ namespace Prism
|
||||
constexpr uint32_t cubemapSize = 2048;
|
||||
constexpr uint32_t irradianceMapSize = 32;
|
||||
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
|
||||
Ref<TextureCube> envUnfiltered = TextureCube::Create(TextureFormat::RGBA16F, cubemapSize, cubemapSize);
|
||||
if (!equirectangularConversionShader)
|
||||
equirectangularConversionShader = Shader::Create("assets/shaders/EquirectangularToCubeMap.glsl");
|
||||
@ -349,11 +351,11 @@ namespace Prism
|
||||
|
||||
equirectangularConversionShader->Bind();
|
||||
envEquirect->Bind();
|
||||
Renderer::Submit([envUnfiltered, cubemapSize, envEquirect]()
|
||||
Renderer::Submit([envUnfiltered, cubemapSize, envEquirect, cmd]()
|
||||
{
|
||||
glBindImageTexture(0, envUnfiltered->GetRendererID(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F);
|
||||
glDispatchCompute(cubemapSize / 32, cubemapSize / 32, 6);
|
||||
glGenerateTextureMipmap(envUnfiltered->GetRendererID());
|
||||
cmd->BindImageTexture(0, envUnfiltered->GetRendererID(), 0, true, 0, AccessMode::WriteOnly, TextureFormat::RGBA16F);
|
||||
cmd->DispatchCompute(cubemapSize / 32, cubemapSize / 32, 6);
|
||||
cmd->GenerateMipmap(envUnfiltered->GetRendererID());
|
||||
});
|
||||
|
||||
|
||||
@ -362,24 +364,26 @@ namespace Prism
|
||||
|
||||
Ref<TextureCube> envFiltered = TextureCube::Create(TextureFormat::RGBA16F, cubemapSize, cubemapSize);
|
||||
|
||||
Renderer::Submit([envUnfiltered, envFiltered]()
|
||||
Renderer::Submit([envUnfiltered, envFiltered, cmd]()
|
||||
{
|
||||
glCopyImageSubData(envUnfiltered->GetRendererID(), GL_TEXTURE_CUBE_MAP, 0, 0, 0, 0,
|
||||
envFiltered->GetRendererID(), GL_TEXTURE_CUBE_MAP, 0, 0, 0, 0,
|
||||
envFiltered->GetWidth(), envFiltered->GetHeight(), 6);
|
||||
cmd->CopyImageSubData(envUnfiltered->GetRendererID(), envFiltered->GetRendererID(),
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
envFiltered->GetWidth(), envFiltered->GetHeight(), 6);
|
||||
});
|
||||
|
||||
envFilteringShader->Bind();
|
||||
envUnfiltered->Bind();
|
||||
|
||||
Renderer::Submit([envUnfiltered, envFiltered, cubemapSize]() {
|
||||
Renderer::Submit([envUnfiltered, envFiltered, cubemapSize, cmd]() {
|
||||
const float deltaRoughness = 1.0f / glm::max((float)(envFiltered->GetMipLevelCount() - 1.0f), 1.0f);
|
||||
for (int level = 1, size = cubemapSize / 2; level < (int)envFiltered->GetMipLevelCount(); level++, size /= 2) // <= ?
|
||||
{
|
||||
const GLuint numGroups = glm::max(1, size / 32);
|
||||
glBindImageTexture(0, envFiltered->GetRendererID(), level, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F);
|
||||
glProgramUniform1f(envFilteringShader->GetRendererID(), 0, level * deltaRoughness);
|
||||
glDispatchCompute(numGroups, numGroups, 6);
|
||||
const uint32_t numGroups = glm::max(1, size / 32);
|
||||
cmd->BindImageTexture(0, envFiltered->GetRendererID(), level, true, 0, AccessMode::WriteOnly, TextureFormat::RGBA16F);
|
||||
// 设置 uniform(这里假设 uniform 位置 0 是 roughness)
|
||||
cmd->ProgramUniform1f(envFilteringShader->GetRendererID(), 0, level * deltaRoughness);
|
||||
cmd->DispatchCompute(numGroups, numGroups, 6);
|
||||
cmd->MemoryBarrier(MemoryBarrierMask::ShaderImageAccess);
|
||||
}
|
||||
});
|
||||
|
||||
@ -389,11 +393,12 @@ namespace Prism
|
||||
Ref<TextureCube> irradianceMap = TextureCube::Create(TextureFormat::RGBA16F, irradianceMapSize, irradianceMapSize);
|
||||
envIrradianceShader->Bind();
|
||||
envFiltered->Bind();
|
||||
Renderer::Submit([irradianceMap]()
|
||||
Renderer::Submit([irradianceMap, cmd]()
|
||||
{
|
||||
glBindImageTexture(0, irradianceMap->GetRendererID(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F);
|
||||
glDispatchCompute(irradianceMap->GetWidth() / 32, irradianceMap->GetHeight() / 32, 6);
|
||||
glGenerateTextureMipmap(irradianceMap->GetRendererID());
|
||||
cmd->BindImageTexture(0, irradianceMap->GetRendererID(), 0, true, 0, AccessMode::WriteOnly, TextureFormat::RGBA16F);
|
||||
cmd->DispatchCompute(irradianceMap->GetWidth() / 32, irradianceMap->GetHeight() / 32, 6);
|
||||
cmd->GenerateMipmap(irradianceMap->GetRendererID());
|
||||
cmd->MemoryBarrier(MemoryBarrierMask::ShaderImageAccess);
|
||||
});
|
||||
|
||||
return { envFiltered, irradianceMap };
|
||||
@ -405,6 +410,7 @@ namespace Prism
|
||||
Ref<TextureCube> Renderer3D::CreatePreethamSky(const glm::vec3& turbidityAzimuthInclination)
|
||||
{
|
||||
constexpr uint32_t cubemapSize = 2048;
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
|
||||
Ref<TextureCube> environmentMap = TextureCube::Create(TextureFormat::RGBA16F, cubemapSize, cubemapSize);
|
||||
|
||||
@ -415,12 +421,13 @@ namespace Prism
|
||||
|
||||
preethamSkyShader->SetFloat3("u_TurbidityAzimuthInclination", turbidityAzimuthInclination);
|
||||
|
||||
Renderer::Submit([environmentMap, cubemapSize]()
|
||||
|
||||
Renderer::Submit([environmentMap, cubemapSize, cmd]()
|
||||
{
|
||||
glBindImageTexture(0, environmentMap->GetRendererID(), 0, GL_TRUE, 0, GL_WRITE_ONLY, GL_RGBA16F);
|
||||
glDispatchCompute(cubemapSize / 32, cubemapSize / 32, 6);
|
||||
glMemoryBarrier(GL_SHADER_IMAGE_ACCESS_BARRIER_BIT);
|
||||
glGenerateTextureMipmap(environmentMap->GetRendererID());
|
||||
cmd->BindImageTexture(0, environmentMap->GetRendererID(), 0, true, 0, AccessMode::WriteOnly, TextureFormat::RGBA16F);
|
||||
cmd->DispatchCompute(cubemapSize / 32, cubemapSize / 32, 6);
|
||||
cmd->MemoryBarrier(MemoryBarrierMask::ShaderImageAccess);
|
||||
cmd->GenerateMipmap(environmentMap->GetRendererID());
|
||||
});
|
||||
|
||||
return environmentMap;
|
||||
@ -513,64 +520,69 @@ namespace Prism
|
||||
float dt = ae.ExposureTimer;
|
||||
ae.ExposureTimer.Reset();
|
||||
|
||||
Renderer::Submit([srcFB, dstFB, logMin = ae.LogMin, logMax = ae.LogMax, histCS = ae.HistogramCS, histSSBO = ae.HistogramSSBO]() {
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFB->GetRendererID());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glDrawBuffer(GL_COLOR_ATTACHMENT0);
|
||||
glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||
0, 0, dstFB->GetWidth(), dstFB->GetHeight(),
|
||||
GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
|
||||
const uint32_t zero = 0;
|
||||
glClearNamedBufferData(histSSBO->GetRendererID(), GL_R32UI, GL_RED, GL_UNSIGNED_INT, &zero);
|
||||
Renderer::Submit([cmd, srcFB, dstFB, logMin = ae.LogMin, logMax = ae.LogMax, histCS = ae.HistogramCS, histSSBO = ae.HistogramSSBO, ae, dt]() {
|
||||
cmd->BindFramebuffer(FramebufferTarget::Read, srcFB->GetRendererID());
|
||||
cmd->BindFramebuffer(FramebufferTarget::Draw, dstFB->GetRendererID());
|
||||
|
||||
glUseProgram(histCS->GetRendererID());
|
||||
glBindTextureUnit(0, dstFB->GetColorAttachmentRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, histSSBO->GetRendererID());
|
||||
cmd->SetReadBuffer(0);
|
||||
cmd->SetDrawBuffer(0);
|
||||
|
||||
const GLint locLogMin = glGetUniformLocation(histCS->GetRendererID(), "u_LogMin");
|
||||
const GLint locLogMax = glGetUniformLocation(histCS->GetRendererID(), "u_LogMax");
|
||||
if (locLogMin != -1) glProgramUniform1f(histCS->GetRendererID(), locLogMin, logMin);
|
||||
if (locLogMax != -1) glProgramUniform1f(histCS->GetRendererID(), locLogMax, logMax);
|
||||
cmd->BlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(), 0, 0, dstFB->GetWidth(), dstFB->GetHeight(),BlitMask::Color, BlitFilter::Nearest);
|
||||
|
||||
const uint32_t groupsX = (dstFB->GetWidth() + 15) / 16;
|
||||
const uint32_t groupsY = (dstFB->GetHeight() + 15) / 16;
|
||||
glDispatchCompute(groupsX, groupsY, 1);
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
});
|
||||
cmd->BindFramebuffer(FramebufferTarget::Read, 0);
|
||||
cmd->BindFramebuffer(FramebufferTarget::Draw, 0);
|
||||
|
||||
Renderer::Submit([&ae, dt]() {
|
||||
glUseProgram(ae.ExposureCS->GetRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ae.HistogramSSBO->GetRendererID());
|
||||
glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 1, ae.ExposureSSBO->GetRendererID());
|
||||
constexpr uint32_t zero = 0;
|
||||
cmd->ClearBufferData(histSSBO, BufferFormat::R32UI, PixelFormat::RED, DataType::UnsignedInt, &zero);
|
||||
|
||||
auto setUniform = [&](const char* name, const float value) {
|
||||
const GLint loc = glGetUniformLocation(ae.ExposureCS->GetRendererID(), name);
|
||||
if (loc != -1) glProgramUniform1f(ae.ExposureCS->GetRendererID(), loc, value);
|
||||
};
|
||||
cmd->UseProgram(histCS->GetRendererID());
|
||||
|
||||
setUniform("u_SpeedUp", ae.SpeedUp);
|
||||
setUniform("u_SpeedDown", ae.SpeedDown);
|
||||
setUniform("u_Key", ae.Key);
|
||||
setUniform("u_LowPercent", ae.LowPercent);
|
||||
setUniform("u_HighPercent", ae.HighPercent);
|
||||
setUniform("u_MinExposure", ae.MinExposure);
|
||||
setUniform("u_MaxExposure", ae.MaxExposure);
|
||||
setUniform("u_DeltaTime", dt);
|
||||
setUniform("u_LogMin", ae.LogMin);
|
||||
setUniform("u_LogMax", ae.LogMax);
|
||||
cmd->BindTextureUnit(0, dstFB->GetColorAttachmentRendererID());
|
||||
cmd->BindStorageBuffer(1, histSSBO);
|
||||
|
||||
glDispatchCompute(1, 1, 1);
|
||||
glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
|
||||
});
|
||||
|
||||
|
||||
int32_t logMinLoc = cmd->GetUniformLocation(histCS->GetRendererID(), "u_LogMin");
|
||||
int32_t logMaxLoc = cmd->GetUniformLocation(histCS->GetRendererID(), "u_LogMax");
|
||||
if (logMinLoc != -1) cmd->ProgramUniform1f(histCS->GetRendererID(), logMinLoc, logMin);
|
||||
if (logMaxLoc != -1) cmd->ProgramUniform1f(histCS->GetRendererID(), logMaxLoc, logMax);
|
||||
|
||||
const uint32_t groupsX = (dstFB->GetWidth() + 15) / 16;
|
||||
const uint32_t groupsY = (dstFB->GetHeight() + 15) / 16;
|
||||
cmd->DispatchCompute(groupsX, groupsY, 1);
|
||||
cmd->MemoryBarrier(MemoryBarrierMask::ShaderStorage);
|
||||
|
||||
cmd->UseProgram(ae.ExposureCS->GetRendererID());
|
||||
cmd->BindStorageBuffer(0, ae.HistogramSSBO);
|
||||
cmd->BindStorageBuffer(1, ae.ExposureSSBO);
|
||||
|
||||
auto setUniform = [&](const char* name, const float value) {
|
||||
const int32_t loc = cmd->GetUniformLocation(ae.ExposureCS->GetRendererID(), name);
|
||||
if (loc != -1) cmd->ProgramUniform1f(ae.ExposureCS->GetRendererID(), loc, value);
|
||||
};
|
||||
|
||||
setUniform("u_SpeedUp", ae.SpeedUp);
|
||||
setUniform("u_SpeedDown", ae.SpeedDown);
|
||||
setUniform("u_Key", ae.Key);
|
||||
setUniform("u_LowPercent", ae.LowPercent);
|
||||
setUniform("u_HighPercent", ae.HighPercent);
|
||||
setUniform("u_MinExposure", ae.MinExposure);
|
||||
setUniform("u_MaxExposure", ae.MaxExposure);
|
||||
setUniform("u_DeltaTime", dt);
|
||||
setUniform("u_LogMin", ae.LogMin);
|
||||
setUniform("u_LogMax", ae.LogMax);
|
||||
|
||||
cmd->DispatchCompute(1, 1, 1);
|
||||
cmd->MemoryBarrier(MemoryBarrierMask::ShaderImageAccess);
|
||||
});
|
||||
}
|
||||
|
||||
void Renderer3D::ShadowMapPass()
|
||||
{
|
||||
const auto& directionalLights = s_Data.SceneData.SceneLightEnvironment.DirectionalLights;
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
if (!s_Data.ShadowEnabled || directionalLights[0].Intensity == 0.0f || !directionalLights[0].CastShadows)
|
||||
{
|
||||
// Clear shadow maps
|
||||
@ -589,10 +601,10 @@ namespace Prism
|
||||
const glm::mat4 lightProjection = glm::ortho(-orthoSize, orthoSize, -orthoSize, orthoSize, nearPlane, farPlane);
|
||||
const glm::mat4 lightSpaceMatrix = lightProjection * lightView;
|
||||
|
||||
Renderer::Submit([]()
|
||||
// auto cmd = Renderer::GetCommandBuffer();
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glEnable(GL_CULL_FACE);
|
||||
glCullFace(GL_BACK);
|
||||
cmd->SetCullMode(CullMode::Back);
|
||||
});
|
||||
|
||||
{
|
||||
@ -617,12 +629,16 @@ namespace Prism
|
||||
{
|
||||
const bool outline = !s_Data.SelectedMeshDrawList.empty();
|
||||
const bool collider = !s_Data.ColliderDrawList.empty();
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
|
||||
if (outline)
|
||||
{
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
|
||||
cmd->SetStencilTest(true); // 开启模板测试
|
||||
cmd->SetStencilOp(StencilOp::Replace, StencilOp::Replace, StencilOp::Replace);
|
||||
cmd->SetStencilFunc(CompareOp::Always, 1, 0xFF); // 总是通过,写入参考值1
|
||||
cmd->SetStencilMask(0xFF);
|
||||
});
|
||||
}
|
||||
|
||||
@ -630,9 +646,9 @@ namespace Prism
|
||||
|
||||
if (outline)
|
||||
{
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glStencilMask(0);
|
||||
cmd->SetStencilMask(0);
|
||||
});
|
||||
}
|
||||
|
||||
@ -689,24 +705,27 @@ namespace Prism
|
||||
auto reg = rd->GetRegister();
|
||||
auto tex = s_Data.ShadowMapRenderPass->GetSpecification().TargetFramebuffer->GetDepthAttachmentRendererID();
|
||||
|
||||
Renderer::Submit([reg, tex]() mutable
|
||||
Renderer::Submit([reg, tex, cmd]() mutable
|
||||
{
|
||||
glBindTextureUnit(reg, tex);
|
||||
glBindSampler(reg++, s_Data.ShadowMapSampler);
|
||||
cmd->BindTextureUnit(reg, tex);
|
||||
cmd->BindSampler(reg, s_Data.ShadowMapSampler);
|
||||
});
|
||||
}
|
||||
|
||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.MaterialInstances);
|
||||
}
|
||||
|
||||
// TODO: bug outline is not correct
|
||||
/*
|
||||
if (outline)
|
||||
{
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xff);
|
||||
glStencilMask(0xff);
|
||||
cmd->SetStencilFunc(CompareOp::Always, 1, 0xff);
|
||||
cmd->SetStencilMask(0xFF);
|
||||
});
|
||||
}
|
||||
*/
|
||||
for (auto& dc : s_Data.SelectedMeshDrawList)
|
||||
{
|
||||
auto baseMaterial = dc.mesh->GetMaterial();
|
||||
@ -756,15 +775,14 @@ namespace Prism
|
||||
|
||||
if (outline)
|
||||
{
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glStencilFunc(GL_NOTEQUAL, 1, 0xff);
|
||||
glStencilMask(0);
|
||||
|
||||
glLineWidth(10);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
cmd->SetStencilTest(true); // 确保模板测试开启
|
||||
cmd->SetStencilFunc(CompareOp::NotEqual, 1, 0xff);
|
||||
cmd->SetStencilMask(0);
|
||||
cmd->SetLineWidth(10);
|
||||
cmd->SetPolygonMode(PolygonMode::Line);
|
||||
cmd->SetDepthTest(false);
|
||||
});
|
||||
|
||||
// Draw outline here
|
||||
@ -776,10 +794,10 @@ namespace Prism
|
||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.mesh->IsAnimated() ? s_Data.OutlineAnimMaterial : s_Data.OutlineMaterial);
|
||||
}
|
||||
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glPointSize(10);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
||||
cmd->SetPointSize(10);
|
||||
cmd->SetPolygonMode(PolygonMode::Point);
|
||||
});
|
||||
for (auto& dc : s_Data.SelectedMeshDrawList)
|
||||
{
|
||||
@ -787,23 +805,24 @@ namespace Prism
|
||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, dc.mesh->IsAnimated() ? s_Data.OutlineAnimMaterial : s_Data.OutlineMaterial);
|
||||
}
|
||||
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glStencilMask(0xff);
|
||||
glStencilFunc(GL_ALWAYS, 1, 0xff);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
cmd->SetPolygonMode(PolygonMode::Fill);
|
||||
cmd->SetStencilMask(0xff);
|
||||
cmd->SetStencilFunc(CompareOp::Always, 1, 0xff);
|
||||
cmd->SetDepthTest(true);
|
||||
cmd->SetStencilTest(false);
|
||||
});
|
||||
}
|
||||
|
||||
if (collider)
|
||||
{
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glLineWidth(1);
|
||||
glEnable(GL_LINE_SMOOTH);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
cmd->SetLineWidth(1);
|
||||
cmd->SetLineSmooth(true);
|
||||
cmd->SetPolygonMode(PolygonMode::Line);
|
||||
cmd->SetDepthTest(false);
|
||||
});
|
||||
|
||||
s_Data.ColliderMaterial->Set("u_ViewProjection", cameraViewProjection);
|
||||
@ -813,10 +832,10 @@ namespace Prism
|
||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.ColliderMaterial);
|
||||
}
|
||||
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glPointSize(1);
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
|
||||
cmd->SetPointSize(1);
|
||||
cmd->SetPolygonMode(PolygonMode::Point);
|
||||
});
|
||||
|
||||
for (auto& dc : s_Data.ColliderDrawList)
|
||||
@ -825,10 +844,10 @@ namespace Prism
|
||||
Renderer::SubmitMesh(dc.mesh, dc.Transform, s_Data.ColliderMaterial);
|
||||
}
|
||||
|
||||
Renderer::Submit([]()
|
||||
Renderer::Submit([cmd]()
|
||||
{
|
||||
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
cmd->SetPolygonMode(PolygonMode::Fill);
|
||||
cmd->SetDepthTest(true);
|
||||
});
|
||||
}
|
||||
|
||||
@ -906,11 +925,12 @@ namespace Prism
|
||||
void Renderer3D::GridPass()
|
||||
{
|
||||
Renderer::BeginRenderPass(s_Data.GeoPass, false);
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
|
||||
if (const auto option = GetOptions(); option.ShowGrid)
|
||||
{
|
||||
Renderer::Submit([]() {
|
||||
glDepthMask(GL_FALSE);
|
||||
Renderer::Submit([cmd]() {
|
||||
cmd->SetDepthWrite(false);
|
||||
});
|
||||
|
||||
const auto& sceneCamera = s_Data.SceneData.SceneCamera;
|
||||
@ -933,43 +953,27 @@ namespace Prism
|
||||
|
||||
Renderer::SubmitFullscreenQuad(s_Data.GridData.GridMaterial);
|
||||
|
||||
Renderer::Submit([]() {
|
||||
glDepthMask(GL_TRUE);
|
||||
Renderer::Submit([cmd]() {
|
||||
cmd->SetDepthWrite(true);
|
||||
});
|
||||
}
|
||||
|
||||
Renderer::EndRenderPass();
|
||||
}
|
||||
|
||||
void CopyDepthBuffer(Ref<FrameBuffer> src, Ref<FrameBuffer> dst)
|
||||
{
|
||||
uint32_t srcID = src->GetRendererID(); // 假设 FrameBuffer 有此方法
|
||||
uint32_t dstID = dst->GetRendererID();
|
||||
|
||||
int srcWidth = src->GetWidth();
|
||||
int srcHeight = src->GetHeight();
|
||||
int dstWidth = dst->GetWidth();
|
||||
int dstHeight = dst->GetHeight();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcID);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstID);
|
||||
glBlitFramebuffer(0, 0, srcWidth, srcHeight, 0, 0, dstWidth, dstHeight,
|
||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0); // 可选恢复
|
||||
}
|
||||
|
||||
void Renderer3D::CompositePass(const Ref<RenderPass>& outRenderPass)
|
||||
{
|
||||
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
Renderer::Submit([srcFB = s_Data.GeoPass->GetSpecification().TargetFramebuffer,
|
||||
dstFB = outRenderPass->GetSpecification().TargetFramebuffer]()
|
||||
dstFB = outRenderPass->GetSpecification().TargetFramebuffer, cmd]()
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID());
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFB->GetRendererID());
|
||||
glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||
0, 0, dstFB->GetWidth(), dstFB->GetHeight(),
|
||||
GL_DEPTH_BUFFER_BIT, GL_NEAREST);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
cmd->BindFramebuffer(FramebufferTarget::Read, srcFB->GetRendererID());
|
||||
cmd->BindFramebuffer(FramebufferTarget::Draw, dstFB->GetRendererID());
|
||||
cmd->BlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||
0, 0, dstFB->GetWidth(), dstFB->GetHeight(),
|
||||
BlitMask::Depth, BlitFilter::Nearest);
|
||||
|
||||
cmd->BindFramebuffer(0);
|
||||
});
|
||||
|
||||
Renderer::BeginRenderPass(outRenderPass);
|
||||
@ -1036,22 +1040,9 @@ namespace Prism
|
||||
s_Data.ResolvedHDRTexture = Texture2D::Create(TextureFormat::RGBA16F, width, height);
|
||||
}
|
||||
|
||||
Renderer::Submit([srcFB, resolvedTex = s_Data.ResolvedHDRTexture]() {
|
||||
GLuint resolveFBO;
|
||||
glGenFramebuffers(1, &resolveFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
|
||||
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolvedTex->GetRendererID(), 0);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFB->GetRendererID());
|
||||
glReadBuffer(GL_COLOR_ATTACHMENT0);
|
||||
|
||||
glBlitFramebuffer(0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||
0, 0, srcFB->GetWidth(), srcFB->GetHeight(),
|
||||
GL_COLOR_BUFFER_BIT, GL_LINEAR);
|
||||
|
||||
glDeleteFramebuffers(1, &resolveFBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
|
||||
auto cmd = Renderer::GetCommandBuffer();
|
||||
Renderer::Submit([srcFB, resolvedTex = s_Data.ResolvedHDRTexture, cmd]() {
|
||||
cmd->ResolveMultisampleTexture(srcFB, resolvedTex);
|
||||
});
|
||||
}
|
||||
|
||||
@ -1178,3 +1169,4 @@ namespace Prism
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -7,6 +7,7 @@
|
||||
|
||||
namespace Prism
|
||||
{
|
||||
enum class PrimitiveType;
|
||||
|
||||
using RendererID = unsigned int;
|
||||
|
||||
@ -16,12 +17,6 @@ namespace Prism
|
||||
OpenGL
|
||||
};
|
||||
|
||||
// TODO: move into separate header
|
||||
enum class PrimitiveType
|
||||
{
|
||||
None = 0, Triangles, Lines
|
||||
};
|
||||
|
||||
struct RenderAPICapabilities
|
||||
{
|
||||
std::string Vendor;
|
||||
|
||||
Reference in New Issue
Block a user