Files
PlantAI-dev/tools/pymol-open-source/layer0/ShaderMgr.h
T
2026-08-03 18:42:47 +08:00

445 lines
14 KiB
C++

/*
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* copyright Schrodinger, LLC.
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information.
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-*
-*
-*
Z* -------------------------------------------------------------------
*/
#ifndef _SHADER_MGR_H
#define _SHADER_MGR_H
#include "os_gl.h"
#include "PyMOLGlobals.h"
#include "Rep.h"
#include "GenericBuffer.h"
#include "SceneDef.h"
#include "ShaderPreprocessor.h"
#include "PostProcess.h"
#include <map>
#include <set>
#include <string>
#include <unordered_map>
#ifdef _WEBGL
#define GET_FRAGDEPTH_SUPPORT() webpymol_get_fragdepth_support()
#else
#define GET_FRAGDEPTH_SUPPORT() 1
#endif
#if !defined(_WEBGL)
#include <mutex>
#define LOCK_GUARD_MUTEX(name, var) std::lock_guard<std::mutex> name(var)
#else
#define LOCK_GUARD_MUTEX(name, var)
#endif
class CShaderPrg {
public:
struct GeometryShaderParams
{
std::string file = "";
GLenum input{};
GLenum output{};
int numVertsOut{};
GLuint id{};
};
struct TessellationShaderParams
{
std::string controlFile = "";
std::string evaluationFile = "";
GLuint controlID{};
GLuint evaluationID{};
};
const std::string name, vertfile, fragfile;
pymol::copyable_ptr<GeometryShaderParams> geomParams;
pymol::copyable_ptr<TessellationShaderParams> tessParams;
std::map<int, std::string> uniformLocations;
std::string derivative;
bool is_valid;
bool is_linked;
CShaderPrg(PyMOLGlobals* G_, const std::string& name,
const std::string& vertfile, const std::string& fragfile,
pymol::copyable_ptr<GeometryShaderParams> geomParams = nullptr,
pymol::copyable_ptr<TessellationShaderParams> tessParams = nullptr)
: name(name)
, geomParams(std::move(geomParams))
, tessParams(std::move(tessParams))
, vertfile(vertfile)
, fragfile(fragfile)
, is_valid(false)
, is_linked(false)
, G(G_)
{
}
bool reload();
/*
* Create a derivative copy. This will reload with ShaderMgr::Reload_Derivatives.
*/
CShaderPrg* DerivativeCopy(
const std::string& name, const std::string& variable)
{
CShaderPrg* copy =
new CShaderPrg(G, name, vertfile, fragfile, geomParams, tessParams);
copy->derivative = variable;
return copy;
}
/* Enable */
int Enable();
/* Disable */
int Disable();
/* Link and IsLinked */
int Link();
int IsLinked();
/* accessors/mutators/uniform setters */
int Set1i(const char * name, int i);
int Set1f(const char * name, float f);
int Set2f(const char * name, float f1, float f2);
int Set3f(const char * name, float f1, float f2, float f3);
int Set4fv(const char * name, const float *f);
int Set3fv(const char * name, const float *f);
int Set4f(const char * name, float f1, float f2, float f3, float f4);
int SetMat3fc(const char * name, const GLfloat * m);
int SetMat4fc(const char * name, const GLfloat * m);
int GetUniformLocation(const char * name);
int GetAttribLocation(const char * name);
void SetAttrib4fLocation(const char * name, float f1, float f2, float f3, float f4);
void SetAttrib1fLocation(const char * name, float f1);
int SetLightingEnabled(int);
void SetBgUniforms();
void Set_Stereo_And_AnaglyphMode();
void Set_AnaglyphMode(int mode);
void Set_Matrices();
void Set_Specular_Values();
void Invalidate();
void ErrorMsgWithShaderInfoLog(const GLuint sid, const char * msg);
public:
PyMOLGlobals * G;
/* openGL assigned id */
int id{};
/* openGL fragment and vertex shader ids */
GLuint vid{};
GLuint fid{};
std::map<std::string, int> uniforms;
std::map<std::string, int> attributes;
int uniform_set{}; // bitmask
};
/* ============================================================================
* CShaderMgr class -- simple ShaderMgr for PyMOL
* ============================================================================*/
class CShaderMgr {
public:
CShaderMgr(PyMOLGlobals * G);
~CShaderMgr();
void Config();
void Set_Reload_Bits(int bits);
void Check_Reload();
GLfloat *GetLineWidthRange();
template <typename T, typename... TArgs>
T * newGPUBuffer(TArgs&&... args) {
std::hash<gpuBuffer_t *> hash_fn;
T * buffer = new T(std::forward<TArgs>(args)...);
auto bufptr = dynamic_cast<gpuBuffer_t *>(buffer);
const size_t hashid = hash_fn(bufptr);
buffer->set_hash_id(hashid);
_gpu_object_map[hashid] = buffer;
return buffer;
}
template <typename T>
T * getGPUBuffer(size_t hashid) {
auto search = _gpu_object_map.find(hashid);
if (search != _gpu_object_map.end())
return dynamic_cast<T*>(search->second);
else
return nullptr;
}
void bindGPUBuffer(size_t hashid);
void freeGPUBuffer(size_t handle);
void freeGPUBuffers(std::vector<size_t> && handles);
void freeGPUBuffers(size_t * arr, size_t len);
#ifndef _PYMOL_NO_AA_SHADERS
bool Reload_SMAA_Shaders();
int SMAAShadersPresent();
CShaderPrg *Enable_FXAAShader();
CShaderPrg *Enable_SMAA1Shader();
CShaderPrg *Enable_SMAA2Shader();
CShaderPrg *Enable_SMAA3Shader();
CShaderPrg *Enable_SMAAShader(const char *shaderName);
#endif
void Reload_Shader_Variables();
/* AddShader -- Adds to the global shader library */
int AddShaderPrg(CShaderPrg * s);
/* RemoveShader -- Removes shader program by name */
int RemoveShaderPrg(const std::string& name);
/* GetShaderPrg -- gets a ptr to the installed shader */
CShaderPrg * GetShaderPrg(std::string name, short set_current_shader = 1, RenderPass pass = RenderPass::Antialias);
int ShaderPrgExists(const char * name);
/* runtime check for shaders */
int ShadersPresent();
int GeometryShadersPresent();
void AddVBOsToFree(GLuint *vboid, int nvbos);
void AddVBOToFree(GLuint vboid);
void FreeAllVBOs();
CShaderPrg *Enable_DefaultShader(RenderPass pass);
CShaderPrg *Enable_LineShader(RenderPass pass);
CShaderPrg *Enable_SurfaceShader(RenderPass pass);
CShaderPrg *Enable_DefaultShaderWithSettings(const CSetting * set1, const CSetting * set2, RenderPass pass);
CShaderPrg *Enable_CylinderShader(const char *, RenderPass pass);
CShaderPrg *Enable_CylinderShader(RenderPass pass);
CShaderPrg *Enable_DefaultSphereShader(RenderPass pass);
CShaderPrg *Enable_RampShader();
CShaderPrg *Enable_ConnectorShader(RenderPass pass);
CShaderPrg *Enable_TriLinesShader();
CShaderPrg *Enable_ScreenShader();
CShaderPrg *Enable_LabelShader(RenderPass pass);
CShaderPrg *Enable_OITShader();
CShaderPrg *Enable_OITCopyShader();
CShaderPrg *Enable_IndicatorShader();
CShaderPrg *Enable_BackgroundShader();
CShaderPrg* Enable_BezierShader();
void Disable_Current_Shader();
CShaderPrg *Get_ScreenShader();
CShaderPrg *Get_ConnectorShader(RenderPass pass);
CShaderPrg *Get_DefaultShader(RenderPass pass);
CShaderPrg *Get_LineShader(RenderPass pass);
CShaderPrg *Get_SurfaceShader(RenderPass pass);
CShaderPrg *Get_CylinderShader(RenderPass pass, short set_current_shader=1);
CShaderPrg *Get_CylinderNewShader(RenderPass pass, short set_current_shader=1);
CShaderPrg *Get_DefaultSphereShader(RenderPass pass);
CShaderPrg *Get_RampShader();
CShaderPrg *Get_Current_Shader();
CShaderPrg *Get_IndicatorShader();
CShaderPrg *Get_BackgroundShader();
CShaderPrg *Get_LabelShader(RenderPass pass);
CShaderPrg* Get_BezierShader();
void Reload_CallComputeColorForLight();
void Reload_All_Shaders();
void Invalidate_All_Shaders();
void ResetUniformSet();
void CShaderPrg_SetIsPicking(int is_picking);
void Generate_LightingTexture();
std::string GetShaderSource(const std::string &filename);
CShaderPrg *Setup_LabelShader(CShaderPrg *shaderPrg);
CShaderPrg *Setup_DefaultShader(CShaderPrg *shaderPrg, const CSetting *set1, const CSetting *set2);
void SetIsPicking(int is_picking);
int GetIsPicking();
void SetPreprocVar(const std::string &key, bool value, bool invshaders = true);
/**
* @return a map of shader filenames to their raw source code
*/
static std::map<std::string, const char*>* GetRawShaderCache();
inline static std::uint32_t OpenGLDefaultFramebufferID = 0;
private:
void freeAllGPUBuffers();
void RegisterDependantFileNames(CShaderPrg * shader);
void CollectDependantFileNames(const std::string &filename, std::vector<std::string> &filenames);
void MakeDerivatives(const std::string &suffix, const std::string &variable);
void Reload_Derivatives(const std::string &variable, bool value = true);
void ShaderSourceInvalidate(const char * filename, bool invshaders = true);
void SetShaderSource(const char * filename, const std::string &contents);
public:
PyMOLGlobals * G;
int shaders_present;
#ifndef _WEBGL
// for deleting buffers in the correct thread
std::vector<GLuint> vbos_to_free;
std::mutex vbos_to_free_mutex;
std::mutex gpu_objects_to_free_mutex;
#endif
CShaderPrg *current_shader;
int is_picking;
GLuint lightingTexture;
/* These lookups and arrays are used to dynamically change the shaders
based on preprocessor-like statements within the shaders. These need
string lookups. */
private:
ShaderPreprocessor m_shaderPreprocessor;
std::unordered_map<size_t, gpuBuffer_t*> _gpu_object_map;
std::vector<size_t> _gpu_objects_to_free_vector;
public:
std::map<std::string, CShaderPrg*> programs;
std::map<int, std::string> attribute_uids;
std::map<const std::string, int> attribute_uids_by_name;
int GetAttributeUID(const char * name);
const char *GetAttributeName(int);
short print_warnings;
int reload_bits;
GLfloat line_width_range[2];
short stereo_flag; /* -1 left; 0 = off; 1 = right */
short stereo_blend; /* 0 - no blend, 1 - blend : for right eye stereo in full-screen e.g., anaglyph */
bool stereo_draw_buffer_pass;
// for glDrawBuffer (e.g. GL_BACK, unless we're using QOpenGLWidget)
GLFramebufferConfig defaultBackbuffer{}; // Default framebuffer configuration
GLFramebufferConfig currentFBConfig{}; // Current framebuffer configuration
GLFramebufferConfig topLevelConfig{}; // Final render target in draw loop
// (currently only known by Ortho)
private:
bool is_configured { false };
public:
bool IsConfigured(){ return is_configured; }
// filename -> used by shader
std::map<std::string, std::vector<std::string> > shader_deps;
// Post process render targets
std::size_t offscreen_rt { 0 }; //Texture before postprocessing;
std::size_t offscreen_ortho_rt{};
std::size_t offscreen_sized_image_rt{};
#ifndef _PYMOL_NO_AA_SHADERS
std::unique_ptr<PostProcess> smaa_pp;
#endif
std::unique_ptr<PostProcess> oit_pp;
void bindOffscreen(int width, int height, GridInfo * grid);
void bindOffscreenOIT(int width, int height, int drawbuf = 0);
/**
* @brief Binds an offscreen render target for UI overlay rendering
* @param extent extent of the offscreen render target
* @param clear whether to clear the offscreen render target
* @return framebuffer configuration of bound ortho offscreen render target
*/
GLFramebufferConfig bindOffscreenOrtho(const Extent2D& extent, bool clear = true);
/**
* @brief Binds an offscreen render target for sized rendering
* @param extent extent of the offscreen render target
* @param clear whether to clear the offscreen render target
* @return framebuffer configuration of bound offscreen render target
*/
GLFramebufferConfig bindOffscreenSizedImage(const Extent2D& extent, bool clear = true);
/**
* @brief Reads pixel data from framebuffer
* @param rect the rectangle to read from
* @param srcConfig the framebuffer configuration to read from
* @return pixel data in RGBA format
*/
std::vector<unsigned char> readPixelsFrom(
PyMOLGlobals* G, const Rect2D& rect, const GLFramebufferConfig& srcConfig);
/**
* @brief Draws pixel data to framebuffer
* @param rect the rectangle to draw to
* @param srcPixels the pixel data (RGBA) to draw
* @param dstConfig the framebuffer configuration to draw to
*/
void drawPixelsTo(PyMOLGlobals* G, const Rect2D& rect,
const std::byte* srcPixels,
const GLFramebufferConfig& dstConfig);
/**
* Activates/Binds offscreen render target.
* @param textureIdx offset of texture unit to assign (0 for GL_TEXTURE0, 1
* for GL_TEXTURE1, etc...)
* @note: indices should preferably be passed in as enum or named variable for
* clarity
*/
void activateOffscreenTexture(GLuint textureIdx);
/**
* Sets the current draw buffer for rendering
* @param drawBuffer Buffer to draw to (e.g. GL_BACK)
* @note: This currently assumes the default framebuffer. Prefer
* GLFramebufferConfig coverload.
*/
void setDrawBuffer(GLenum drawBuffer);
/**
* Sets the current framebuffer or draw buffer for rendering
* @param drawBuffer Framebuffer to draw to
*/
void setDrawBuffer(GLFramebufferConfig config);
};
bool ShaderMgrInit(PyMOLGlobals * G);
/* for reload_bits */
enum {
RELOAD_VARIABLES = 0x01,
RELOAD_CALLCOMPUTELIGHTING = 0x02,
RELOAD_ALL_SHADERS = 0xff,
};
#define VERTEX_POS_SIZE 3
#define VERTEX_COLOR_SIZE 4
#define VERTEX_POS 0
#define VERTEX_NORMAL 1
#define VERTEX_COLOR 2
#define CYLINDER_VERTEX1 0
#define CYLINDER_VERTEX2 1
#define CYLINDER_COLOR 2
#define CYLINDER_COLOR2 3
#define CYLINDER_RADIUS 4
#define CYLINDER_CAP 5
#define RAMP_OFFSETPT 0
#endif
// vi:sw=2:expandtab