Files
Webcam/include/engine/gpu/gpu_renderer.h
2026-06-22 11:49:35 +02:00

648 lines
19 KiB
C++

/* -----------------------------------------------------------------------------
GSFramework
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */
#ifndef __GPURENDERER__
#define __GPURENDERER__
#include "gpu/gpu_shader_object.h"
#include "gpu/gpu_fbo.h"
#include "gpu/gpu_vbo.h"
#include "gpu/gpu_render_list.h"
#include "gpu/gpu_draw_context.h"
#include "gpu/gpu_config.h"
#include "gpu/gpu_shader_compiler.h"
#include "gpu/gpu_perf_tools.h"
#include "gpu/gpu_terrain.h"
#include "gpu/gpu_caps.h"
#include "core/render_resource_factory.h"
#include "core/renderer.h"
#include "core/camera.h"
#include "memory/nweak_ptr.h"
namespace GS {
namespace GPU {
class PrepareLightJob;
/*!
@short GPU based renderer class.
@author Emmanuel Julien (ejulien@gsworks.fr)
*/
class Renderer : public Render::Renderer
{
AutoPtr <Render::ResourceFactory> core_resource_factory;
public:
/*!
@name Factories.
@{
*/
virtual FBO *NewFBO() = 0;
virtual VBO *NewVBO() = 0;
virtual DisplayList *NewDisplayList() = 0;
virtual ShaderObject *NewGPUShaderObject() = 0;
/*!
@}
@name Render path.
@{
*/
bool pending_shadow_map_refresh,
pending_core_shader_refresh,
pending_technique_refresh,
pending_fx_refresh;
RendererConfig gpu_config;
PerformanceTools performance_tools;
/// Process registry message.
virtual RegistryRValue ProcessMessage(RegistryMessage message, const Registry *, const void *parm);
/// Query a caps on the renderer.
virtual bool QueryCaps(Caps, Variant &) { return false; }
/// Discover and apply the GPU configuration.
virtual void DiscoverGPUConfiguration();
/// @}
enum RenderTechnique
{
TechniqueDefault = 0,
TechniqueForward, ///< Forward rendering
TechniqueDeferred ///< Deferred rendering for opaque polygons, forward for alpha polygons.
};
RenderTechnique render_technique;
/// Return the default render technique.
RenderTechnique GetDefaultRenderTechnique() const;
/// Refresh render technique.
void RefreshRenderTechnique();
/// Free render technique objects.
void FreeRenderTechnique();
/// Switch to a specific render technique.
void SetRenderTechnique(RenderTechnique = TechniqueDefault);
/// Setup post-process system.
void SetPostProcess(uint k = 0);
/*!
@name Statistics.
@{
*/
RendererStatistics gpu_stats;
/// Draw the renderer profiler output.
virtual void DrawProfilerText(Render::RasterFont *font[2], float &x, float &y);
/// Reset statistics.
virtual void ResetStatistics()
{
gpu_stats.Reset();
stats.Reset();
}
/// @}
/*!
@name State functions.
@{
*/
enum GPUFillMode
{
FillSolid = 0,
FillWireframe,
FillLast
};
/// Set primitive fill mode.
virtual void SetFillMode(GPUFillMode) = 0;
enum GPUCullFunc
{
CullFront = 0,
CullBack,
CullLast
};
/// Set culling function.
virtual void SetCullFunc(GPUCullFunc) = 0;
/// Enable culling.
virtual void EnableCulling(bool) = 0;
enum GPUDepthFunc
{
DepthNever = 0,
DepthLess,
DepthEqual,
DepthLessEqual,
DepthGreater,
DepthNotEqual,
DepthGreaterEqual,
DepthAlways,
DepthFuncLast
};
/// Set depth function.
virtual void SetDepthFunc(GPUDepthFunc) = 0;
/// Set depth read.
virtual void EnableDepthTest(bool) = 0;
/// Set depth write.
virtual void EnableDepthWrite(bool) = 0;
enum BlendFunc
{
BlendZero = 0,
BlendOne,
BlendSrcAlpha,
BlendOneMinusSrcAlpha,
BlendDstAlpha,
BlendOneMinusDstAlpha,
BlendLast
};
/// Set blend function.
virtual void SetBlendFunc(BlendFunc src, BlendFunc dst) = 0;
/// Enable blend.
virtual void EnableBlending(bool) = 0;
/// Enable alpha to coverage.
virtual void EnableAlphaToCoverage(bool) = 0;
/// Enable alpha testing.
virtual void EnableAlphaTest(bool, float threshold = 0.f) = 0;
/// Set vertex buffer object.
virtual void SetVertexSource(VBO *, size_t stride) = 0;
/// Set index buffer object.
virtual void SetIndexSource(VBO *) = 0;
/// Set shader object.
virtual bool SetShaderProgram(Shader *, Shader *unset = 0) = 0;
/// Set display list.
virtual void SetDisplayList(DisplayList *);
protected:
Matrix4 m_projection,
m_view, m_iview,
m_world, m_iworld;
Matrix4 m_previous_iview, // Motion blur specific.
m_previous_world;
/// @}
SharedPtr <Shader>
single_texture_color_program,
single_texture_program,
single_color_program,
simple_program,
tone_mapping_program,
single_texture_cutoff_program,
single_texture_fx_program,
shader_program,
fx_blur_program,
noise_program,
sharpen_program,
hsl_program,
chromatic_dispersion_program,
ssaa_program,
ssao_program,
ssao_blur_program,
radial_blur_program,
motion_blur_program,
skybox_program;
/*!
@name Terrain system.
@{
*/
Array <char> terrain_patch_vtx;
Array <CachedTerrainPatch> terrain_patch_cache;
/// Ensure lower entries will get out of cache.
void DecayTerrainCache();
/// Upload a terrain patch to a cache page.
void UploadTerrainPatchToPage(CachedTerrainPatch &page, const Core::Item &item, const Core::Patch &patch, const DrawContext &dc);
/// Render a terrain patch.
void RenderTerrainPatch(const Core::Patch &, const Core::Item &, const DrawContext &);
public:
/// Set default states.
void SetDefaultStates();
/// Setup core resources.
bool SetupCoreResources(bool support_3d = true);
/// Invalidate the terrain cache.
void InvalidateTerrainCache(int u = 0, int v = 0, int w = 0, int h = 0);
/// Create the static terrain patch.
bool CreateTerrainPatch();
/// @}
/*!
@name Core shader.
@{
*/
protected:
NML::File shader_dict,
material_dict;
/// Marshall core shader source.
void MarshallCoreShader(String &source);
/// Load a shader from a resource file.
Shader *SetupCoreShader(const char *name);
bool LoadCoreShaders(bool support_3d = true);
void UnloadCoreShaders();
public:
AutoPtr <IShaderCompiler> shader_compiler;
List <MaterialShader *> material_shaders;
List <Render::Texture *> textures;
List <Render::Shader *> shaders;
NML::Tag *GetPCFShaderTag() const;
NML::Tag *GetPSMShaderTag() const;
NML::Tag *GetPSSMShaderTag() const;
const NML::File &GetShaderDictionary() const
{ return shader_dict; }
const NML::File &GetMaterialDict() const
{ return material_dict; }
uint fx_scale;
FBO *render_fbo;
bool normal_depth_updated;
AutoPtr <FBO> buffer_fbo, fx_fbo;
Render::sTexture t_compose[2], t_depth; ///< 1:1
Render::sTexture t_color_aa, t_depth_aa; ///< 1:1
Render::sTexture t_fx[3], t_fx_depth; ///< Downscaled FX render targets.
AutoPtr <FBO> resolve_fbo; ///< For MSAA support.
FBO *output_fbo;
iRect output_fbo_rect;
AutoPtr <FBO> shadow_map_fbo;
Render::sTexture shadow_map;
float pcf_radius;
float frame_clock;
Render::sTexture t_noise;
/// @}
/*!
@name Post-processes.
@{
*/
Render::Texture *t_final;
/// Apply directional blur to a texture.
void ApplyDirectionalBlur(Render::Texture *t[2], const Vector2 &d, float attn = 0.975f);
void ApplyBloomFilter(Render::Texture *t, float strength, float threshold, float exponent, float radius, float strength_white_screen);
bool ApplyNoiseFilter(Render::Texture *t_in, Render::Texture *t_out, float strength, float monochromatic, float bias);
bool ApplySharpenFilter(Render::Texture *t_in, Render::Texture *t_out, float strength);
bool ApplyHSL(Render::Texture *t_in, Render::Texture *t_out, float H, float S, float L);
bool ApplyChromaticDispersion(Render::Texture *t_in, Render::Texture *t_out, float width);
bool ApplySSAAFilter(Render::Texture *t_in, Render::Texture *t_out);
bool ApplySSAOFilter(Render::Texture *t_in, Render::Texture *t_out, const Stack <RenderPrimitive *> [2], float strength, float radius, float clip_distance, float blur_radius);
bool ApplyRadialBlur(Render::Texture *t_in, Render::Texture *t_out, float strength, float center_x, float center_y);
bool ApplyMotionBlur(Render::Texture *t_in, Render::Texture *t_out, const Stack <RenderPrimitive *> [2], float strength, int quality = 1);
void GetPostProcessNormalDepth(const Stack <RenderPrimitive *> display_lists[2]);
/// Apply post-processes.
Render::Texture *ApplyPostProcessChain(const Stack <RenderPrimitive *> [2]);
/// @}
/*!
@name Deferred shading.
@{
*/
Render::sTexture t_gbuffer[4];
protected:
struct ViewConfig
{
Core::Camera *camera;
fRect viewport;
ViewConfig(Core::Camera *c, const fRect &v) : camera(c), viewport(v) {}
};
fRect viewport;
fRect clipping;
/// Backup the current view configuration.
ViewConfig BackupView() const;
/// Restore a view configuration.
void RestoreView(const ViewConfig &);
/// Restore a view configuration viewport.
void RestoreViewport(const ViewConfig &);
/// Allocate shadow map.
void CreateShadowMaps();
/// Free shadow map.
void FreeShadowMaps();
AutoPtr <Shader> ambient_program,
pointlight_program,
pointlight_shadow_program,
spotlight_program,
spotlight_shadow_program,
linearlight_program,
linearlight_shadow_program;
AutoPtr <Shader> ds_fog_program;
/// Render fullscreen light volume.
void RenderFullscreenLight(Shader &, Core::Light &);
/// Render point light volume.
void RenderPointLight(Core::Light &, const DrawContext &);
/// Render spot light volume.
void RenderSpotLight(Core::Light &, const DrawContext &);
/// Render linear light volume.
void RenderLinearLight(Core::Light &, const DrawContext &);
public:
struct ShadowMapSplit
{
Core::Camera view;
RenderableList list;
fRect rect;
};
bool LightPreparePSM(const Core::Light &, bool build_dlist) const;
bool LightPreparePSSM(const Core::Light &, bool build_dlist) const;
bool LightPrepareSSM(const Core::Light &, bool build_dlist) const;
/// Prepare shadow map for a light.
bool PrepareShadowMap(const Core::Light &, bool build_dlist) const;
void LightRenderPSM(Core::Light &);
void LightRenderSSM(Core::Light &);
void LightRenderPSSM(Core::Light &);
/// Render shadow map for a light.
void RenderShadowMap(Core::Light &);
/*!
@}
@name Deferred render pass.
@{
*/
protected:
/// Render G-buffer map.
void RenderGBufferPass(const Stack <RenderPrimitive *> &);
/// Render light accumulation map.
void RenderDeferredLightPass(const Stack <RenderPrimitive *> &);
/// Render primitive list using deferred shading.
void RenderListDeferred(const Stack <RenderPrimitive *> &);
/// @}
/*!
@}
@name Forward render pass.
@{
*/
void SetupForwardContext(const DrawContext::Context &);
/// Cull display lists against a given light volume.
void LightCullDisplayList(const Core::Light &, const Stack <RenderPrimitive *> &in, Stack <RenderPrimitive *> &out);
/// Render primitive list using forward rendering.
void RenderListForward(Stack <RenderPrimitive *> &, DrawContext::Render);
void DrawForwardLightContribution(DrawContext::Render, const List <Core::Light *> &, const AutoStack <PrepareLightJob *> &, const Array <Stack <RenderPrimitive *> > &);
void DrawForwardBaseConstant(DrawContext::Render, const Stack <RenderPrimitive *> &);
/// @}
/*!
@name Common render pass.
@{
*/
RenderableList frustum_rlist, shadow_rlist;
struct DisplayListCache
{
DrawContext::Context ctx;
DisplayList *dls;
Material *mat;
Shader *shd;
const Core::Item *item;
float opacity;
DisplayListCache() : dls(0), mat(0), shd(0), item(0), opacity(-1.f) {}
};
DisplayListCache dls_cache;
/// Reset the display list cache.
void ResetDisplayListCache();
/// Set draw context.
bool SetDrawContext(DisplayList &, const Core::Item &, const DrawContext &);
/// Draw a display list using the current renderer cache state.
void DrawDisplayListCached(DisplayList &, const Core::Item &, const DrawContext &);
/// Set direct primitive draw state.
void DrawSetState(Core::Material::BlendOperator bo, Core::Material::RenderWord f);
/// Restore direct primitive draw state.
void DrawRestoreState(Core::Material::BlendOperator bo, Core::Material::RenderWord f);
/// Render skybox.
void DrawSkybox(Render::sTexture [2], Render::Shader * = 0);
public:
/// Draw primitive list using a specific program.
void DrawList(const Stack <RenderPrimitive *> &, const DrawContext &);
/// Build display lists.
void BuildDisplayLists(const AutoStack <Render::Primitive *> &, AutoStack <RenderPrimitive *> *) const;
/// Sort display list per render attributes.
void SortDisplayList(AutoStack <RenderPrimitive *> &) const;
/// @}
/*!
@name Helper functions.
@{
*/
AutoPtr <VBO> helper_idx_vbo, helper_vtx_vbo;
AutoPtr <VBO> skybox_idx_vbo, skybox_vtx_vbo;
AutoPtr <VBO> direct_idx_vbo, direct_vtx_vbo;
AutoPtr <VBO> box_idx_vbo; // for deferred light volume drawing
/// Render a fullscreen quad.
void RenderFullscreenQuad(Shader &, float k_x, float k_y, Render::Texture * = 0, Core::Light * = 0);
void RenderFullscreenQuad(Shader &, const fRect &nUnused(src_rect), const fRect &nUnused(dst_rect), Render::Texture * = 0, Core::Light * = 0);
/// Translate a shader from ISL to the target platform language.
virtual bool TranslateShader(const Core::Shader &, String &, String &) const = 0;
/// Set output FBO object (the current frame buffer is blit over this FBO color attachment in EndDrawList).
void SetOutputFBO(FBO *fbo = 0, const iRect *rect = 0)
{
output_fbo = fbo;
if (rect)
output_fbo_rect = *rect;
}
int GetAnisotropySampleCount(Render::TextureParm::Anisotropy) const;
/// Set current FBO.
virtual void SetCurrentFBO(FBO * = 0) = 0;
/// Check the current FBO state.
virtual bool CheckCurrentFBO() = 0;
struct DirectVertexLayout
{
size_t stride;
size_t vtx_offset, color_offset, uv_offset;
};
/// Helper to build a direct vertex layout from distinct input streams.
bool BuildDirectVertexLayout(uint idx_count, const ushort *idx, const Vector4 *v, const Color *c, const Vector2 *uv, DirectVertexLayout &, VBO *idx_vbo = 0, VBO *vtx_vbo = 0);
/// @}
/*!
@name Performance functions.
@{
*/
/// Set a single shot event.
virtual void PerfSetMarker(const char *name, const Color &) {}
/// Start a performance event.
virtual void PerfBeginEvent(const char *name, const Color &) {}
/// End a performance event.
virtual void PerfEndEvent() {}
//
struct ScopedPerfEvent
{
Renderer *renderer;
ScopedPerfEvent(Renderer *_renderer, const char *name, const Color &color) : renderer(_renderer)
{ renderer->PerfBeginEvent(name, color); }
~ScopedPerfEvent()
{ renderer->PerfEndEvent(); }
};
/// @}
/*!
@name Low-level draw.
@{
*/
/// Set material.
void SetMaterial(const Material &, const DrawContext::Context &, bool force_alpha = false);
/// Unset material.
void UnsetMaterial(const Material &, const DrawContext::Context &);
/// Draw elements.
virtual void DrawElements(Types::PrimitiveType p_type, int index_count, Types::ValueType i_type = Types::ValueLast, const void *indice = 0) = 0;
/// @}
/// Set the view matrix.
void SetViewMatrix(const Matrix4 &, const Matrix4 *inverse = 0);
/// Set the projection matrix.
void SetProjectionMatrix(const Matrix4 &);
/// Set the world matrix.
void SetWorldMatrix(const Matrix4 &, const Matrix4 *inverse = 0);
/// Draw a line to the frame buffer.
virtual void DrawLine(uint count, const Vector4 *, const Color * = 0, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Render::Shader * = 0);
/// Draw a triangle to frame buffer.
virtual void DrawTriangle(uint count, const Vector4 *, const ushort * = 0, const Color * = 0, const Vector2 * = 0, const Render::Texture * = 0, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Render::Shader * = 0);
/// Draw sprite.
virtual void DrawSprite(uint count, const Vector4 *, const Color * = 0, const float *size = 0, const Render::Texture * = 0, float global_size = 1.f, Core::Material::BlendOperator = Core::Material::Blend_None, Core::Material::RenderWord = Core::Material::Render_None, Render::Shader * = 0);
/*!
@name Render-to-texture and spline rendering.
@author Nicolas RACOT
@{
*/
/// Create a render-target texture.
Render::Texture *CreateRenderTexture(const char *name, uint width, uint height, Render::Texture::Format format = Render::Texture::FormatRGBA8, Render::Texture::AA aa = Render::Texture::NoAA);
/// Clear a texture with a solid color.
void ClearTexture(Render::Texture *target, const Color &clear_color = Color(0,0,0,0));
/// Copy/blit a source texture to a destination texture.
void BlitTextureToTexture(Render::Texture *src, Render::Texture *dst, const fRect *src_rect = 0, const fRect *dst_rect = 0);
/// Draw an interpolated spline on a texture with configurable width and color.
void DrawSplineToTexture(Render::Texture *target, const Array<Vector2> &control_points, float width_pixels, const Color &color, int samples_per_segment = 16, bool clear_target = false, bool soft_edge = true, const Color *border_color = nullptr, float border_width = 0.0f, float margin = 0.0f);
private:
/// Helper structure for spline tessellation.
struct SplineRibbon
{
Array<Vector4> positions;
Array<ushort> indices;
Array<Color> colors;
Array<Vector2> uvs; // for soft edge (distance from centerline)
};
/// Catmull-Rom spline interpolation.
Vector2 CatmullRomInterpolate(const Vector2 &p0, const Vector2 &p1, const Vector2 &p2, const Vector2 &p3, float t) const;
/// Tessellate a spline into ribbon geometry.
void TessellateSplineRibbon(const Array<Vector2> &control_points, float width_normalized, const Color &color, int samples_per_segment, bool soft_edge, SplineRibbon &out_ribbon);
public:
/// @}
/// Initialize platform.
virtual bool InitializePlatform() = 0;
/// Open platform video system.
virtual bool OpenPlatformVideo(uint w, uint h, char d, Render::VideoMode m, const void *sys_handle = 0) = 0;
/// Close platform video system.
virtual void ClosePlatformVideo() = 0;
/// Render the display list.
void RenderList();
/// Output string to screen.
virtual void Write(const Render::RasterFont &, const char *, float &x, float &y, const WriterConfig &, float s = 1, const Color *c = 0, WriterAlignment a = AlignLeft, bool mirrored = false);
/// Open video.
virtual bool Open(uint w, uint h, char d = 32, Render::VideoMode m = Render::VideoWindowed, const void *sys_handle = 0);
/// Free all renderer resources.
virtual void Free();
/// Close video.
virtual void Close();
/// Explicitly resize video output.
virtual bool ResizeVideo(uint w, uint h);
/// Begin a drawing operation.
bool BeginDrawList();
/// End a drawing operation.
void EndDrawList();
Renderer();
};
} // GPU
} // GS
#endif // __GPURENDERER__