OpenClonk
C4Shader Class Reference

#include <C4Shader.h>

Public Member Functions

 C4Shader ()
 
 ~C4Shader ()
 
bool Initialised () const
 
GLint GetUniform (int iUniform) const
 
bool HaveUniform (int iUniform) const
 
GLint GetAttribute (int iAttribute) const
 
void AddDefine (const char *name)
 
void AddVertexSlice (int iPos, const char *szText)
 
void AddFragmentSlice (int iPos, const char *szText)
 
void AddVertexSlices (const char *szWhat, const char *szText, const char *szSource="", int iFileTime=0)
 
void AddFragmentSlices (const char *szWhat, const char *szText, const char *szSource="", int iFileTime=0)
 
bool LoadFragmentSlices (C4GroupSet *pGroupSet, const char *szFile)
 
bool LoadVertexSlices (C4GroupSet *pGroupSet, const char *szFile)
 
void SetScriptCategories (const std::vector< std::string > &categories)
 
bool Init (const char *szWhat, const char **szUniforms, const char **szAttributes)
 
bool Refresh ()
 
void ClearSlices ()
 
void Clear ()
 

Static Public Member Functions

static bool IsLogging ()
 

Friends

class C4ShaderCall
 
class C4ScriptUniform
 

Detailed Description

Definition at line 61 of file C4Shader.h.

Constructor & Destructor Documentation

◆ C4Shader()

C4Shader::C4Shader ( )

Definition at line 47 of file C4Shader.cpp.

48  : LastRefresh()
49 {
50 
51 }

◆ ~C4Shader()

C4Shader::~C4Shader ( )

Definition at line 53 of file C4Shader.cpp.

54 {
55  Clear();
56 }
void Clear()
Definition: C4Shader.cpp:335

References Clear().

Here is the call graph for this function:

Member Function Documentation

◆ AddDefine()

void C4Shader::AddDefine ( const char *  name)

Definition at line 65 of file C4Shader.cpp.

66 {
67  StdStrBuf define = FormatString("#define %s", name);
68  AddVertexSlice(-1, define.getData());
69  AddFragmentSlice(-1, define.getData());
70 }
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:270
void AddFragmentSlice(int iPos, const char *szText)
Definition: C4Shader.cpp:77
void AddVertexSlice(int iPos, const char *szText)
Definition: C4Shader.cpp:72
const char * getData() const
Definition: StdBuf.h:442

References AddFragmentSlice(), AddVertexSlice(), FormatString(), and StdStrBuf::getData().

Referenced by C4DefAdditionalResourcesLoader::AddShaderSlices(), and CStdGL::PrepareSpriteShader().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ AddFragmentSlice()

void C4Shader::AddFragmentSlice ( int  iPos,
const char *  szText 
)

Definition at line 77 of file C4Shader.cpp.

78 {
79  AddSlice(FragmentSlices, iPos, szText, nullptr, 0, 0);
80 }

Referenced by AddDefine().

Here is the caller graph for this function:

◆ AddFragmentSlices()

void C4Shader::AddFragmentSlices ( const char *  szWhat,
const char *  szText,
const char *  szSource = "",
int  iFileTime = 0 
)

Definition at line 87 of file C4Shader.cpp.

88 {
89  AddSlices(FragmentSlices, szWhat, szText, szSource, iSourceTime);
90 }

Referenced by C4FoW::GetFramebufShader(), C4FoW::GetRenderShader(), and Refresh().

Here is the caller graph for this function:

◆ AddVertexSlice()

void C4Shader::AddVertexSlice ( int  iPos,
const char *  szText 
)

Definition at line 72 of file C4Shader.cpp.

73 {
74  AddSlice(VertexSlices, iPos, szText, nullptr, 0, 0);
75 }

Referenced by AddDefine().

Here is the caller graph for this function:

◆ AddVertexSlices()

void C4Shader::AddVertexSlices ( const char *  szWhat,
const char *  szText,
const char *  szSource = "",
int  iFileTime = 0 
)

Definition at line 82 of file C4Shader.cpp.

83 {
84  AddSlices(VertexSlices, szWhat, szText, szSource, iSourceTime);
85 }

Referenced by C4FoW::GetFramebufShader(), and C4FoW::GetRenderShader().

Here is the caller graph for this function:

◆ Clear()

void C4Shader::Clear ( )

Definition at line 335 of file C4Shader.cpp.

336 {
337 #ifndef USE_CONSOLE
338  if (!hProg) return;
339  // Need to be detached, then deleted
340  glDeleteProgram(hProg);
341  hProg = 0;
342  // Clear uniform data
343  Uniforms.clear();
344  Attributes.clear();
345 #endif
346 }

Referenced by C4Sky::Clear(), CStdGL::Clear(), CStdGL::PrepareSpriteShader(), and ~C4Shader().

Here is the caller graph for this function:

◆ ClearSlices()

void C4Shader::ClearSlices ( )

Definition at line 324 of file C4Shader.cpp.

325 {
326  VertexSlices.clear();
327  FragmentSlices.clear();
328  iTexCoords = 0;
329  // Script slices
330  ScriptSlicesLoaded = false;
331  Categories.clear();
332  ScriptShaders.clear();
333 }

Referenced by C4FoW::GetFramebufShader(), C4FoW::GetRenderShader(), and CStdGL::PrepareSpriteShader().

Here is the caller graph for this function:

◆ GetAttribute()

GLint C4Shader::GetAttribute ( int  iAttribute) const
inline

Definition at line 127 of file C4Shader.h.

128  {
129  return iAttribute >= 0 && static_cast<unsigned int>(iAttribute) < Attributes.size() ? Attributes[iAttribute].address : -1;
130  }

Referenced by C4LandscapeRenderGL::Draw(), C4ShaderCall::GetAttribute(), and C4FoWRegion::Render().

Here is the caller graph for this function:

◆ GetUniform()

◆ HaveUniform()

bool C4Shader::HaveUniform ( int  iUniform) const
inline

Definition at line 122 of file C4Shader.h.

123  {
124  return GetUniform(iUniform) != GLint(-1);
125  }
GLint GetUniform(int iUniform) const
Definition: C4Shader.h:117

References GetUniform().

Referenced by C4ShaderCall::AllocTexUnit(), C4LandscapeRenderGL::Draw(), C4ShaderCall::SetUniform1f(), C4ShaderCall::SetUniform1fv(), C4ShaderCall::SetUniform1i(), C4ShaderCall::SetUniform1iv(), C4ShaderCall::SetUniform1ui(), C4ShaderCall::SetUniform1uiv(), C4ShaderCall::SetUniform2f(), C4ShaderCall::SetUniform2fv(), C4ShaderCall::SetUniform2i(), C4ShaderCall::SetUniform2iv(), C4ShaderCall::Setuniform2ui(), C4ShaderCall::SetUniform2uiv(), C4ShaderCall::SetUniform3f(), C4ShaderCall::SetUniform3fv(), C4ShaderCall::SetUniform3i(), C4ShaderCall::SetUniform3iv(), C4ShaderCall::Setuniform3ui(), C4ShaderCall::SetUniform3uiv(), C4ShaderCall::SetUniform4f(), C4ShaderCall::SetUniform4fv(), C4ShaderCall::SetUniform4i(), C4ShaderCall::SetUniform4iv(), C4ShaderCall::Setuniform4ui(), C4ShaderCall::SetUniform4uiv(), C4ShaderCall::SetUniformMatrix2x3fv(), C4ShaderCall::SetUniformMatrix3x3(), C4ShaderCall::SetUniformMatrix3x3fv(), C4ShaderCall::SetUniformMatrix3x3Transpose(), C4ShaderCall::SetUniformMatrix3x4(), C4ShaderCall::SetUniformMatrix3x4fv(), C4ShaderCall::SetUniformMatrix4x4(), and C4ShaderCall::SetUniformMatrix4x4fv().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Init()

bool C4Shader::Init ( const char *  szWhat,
const char **  szUniforms,
const char **  szAttributes 
)

Definition at line 348 of file C4Shader.cpp.

349 {
350  Name.Copy(szWhat);
351  LastRefresh = C4TimeMilliseconds::Now();
352 
353  if (!ScriptSlicesLoaded)
354  {
355  Categories.emplace_back(szWhat);
356  LoadScriptSlices();
357  }
358 
359  StdStrBuf VertexShader = Build(VertexSlices, true),
360  FragmentShader = Build(FragmentSlices, true);
361 
362  // Dump
363  if (C4Shader::IsLogging())
364  {
365  ShaderLogF("******** Vertex shader for %s:", szWhat);
366  ShaderLog(VertexShader.getData());
367  ShaderLogF("******** Fragment shader for %s:", szWhat);
368  ShaderLog(FragmentShader.getData());
369  }
370 
371 #ifndef USE_CONSOLE
372  // Attempt to create shaders
373  const GLuint hVert = Create(GL_VERTEX_SHADER,
374  FormatString("%s vertex shader", szWhat).getData(),
375  VertexShader.getData());
376  const GLuint hFrag = Create(GL_FRAGMENT_SHADER,
377  FormatString("%s fragment shader", szWhat).getData(),
378  FragmentShader.getData());
379 
380  if(!hFrag || !hVert)
381  {
382  if (hFrag) glDeleteShader(hFrag);
383  if (hVert) glDeleteShader(hVert);
384  return false;
385  }
386 
387  // Link program
388  const GLuint hNewProg = glCreateProgram();
389  pGL->ObjectLabel(GL_PROGRAM, hNewProg, -1, szWhat);
390  glAttachShader(hNewProg, hVert);
391  glAttachShader(hNewProg, hFrag);
392  glLinkProgram(hNewProg);
393  // Delete vertex and fragment shader after we linked the program
394  glDeleteShader(hFrag);
395  glDeleteShader(hVert);
396 
397  // Link successful?
398  DumpInfoLog(FormatString("%s shader program", szWhat).getData(), hNewProg, true);
399  GLint status;
400  glGetProgramiv(hNewProg, GL_LINK_STATUS, &status);
401  if(status != GL_TRUE) {
402  glDeleteProgram(hNewProg);
403  ShaderLogF(" gl: Failed to link %s shader!", szWhat);
404  return false;
405  }
406  ShaderLogF(" gl: %s shader linked successfully", szWhat);
407 
408  // Everything successful, delete old shader
409  if (hProg != 0) glDeleteProgram(hProg);
410  hProg = hNewProg;
411 
412  // Allocate uniform and attribute arrays
413  int iUniformCount = 0;
414  if (szUniforms != nullptr)
415  while (szUniforms[iUniformCount])
416  iUniformCount++;
417  Uniforms.resize(iUniformCount);
418 
419  int iAttributeCount = 0;
420  if (szAttributes != nullptr)
421  while (szAttributes[iAttributeCount])
422  iAttributeCount++;
423  Attributes.resize(iAttributeCount);
424 
425  // Get uniform and attribute locations. Note this is expected to fail for a few of them
426  // because the respective uniforms got optimized out!
427  for (int i = 0; i < iUniformCount; i++) {
428  Uniforms[i].address = glGetUniformLocation(hProg, szUniforms[i]);
429  Uniforms[i].name = szUniforms[i];
430  ShaderLogF("Uniform %s = %d", szUniforms[i], Uniforms[i].address);
431  }
432 
433  for (int i = 0; i < iAttributeCount; i++) {
434  Attributes[i].address = glGetAttribLocation(hProg, szAttributes[i]);
435  Attributes[i].name = szAttributes[i];
436  ShaderLogF("Attribute %s = %d", szAttributes[i], Attributes[i].address);
437  }
438 
439 #endif
440 
441  return true;
442 }
CStdGL * pGL
Definition: C4DrawGL.cpp:907
bool ShaderLog(const char *szMessage)
Definition: C4Log.cpp:343
bool ShaderLogF(const char *strMessage ...)
Definition: C4Log.cpp:356
static bool IsLogging()
Definition: C4Shader.cpp:665
static C4TimeMilliseconds Now()
void ObjectLabel(uint32_t identifier, uint32_t name, int32_t length, const char *label)
Definition: C4DrawGL.cpp:267
void Copy()
Definition: StdBuf.h:467

References StdStrBuf::Copy(), FormatString(), StdStrBuf::getData(), IsLogging(), C4TimeMilliseconds::Now(), CStdGL::ObjectLabel(), pGL, ShaderLog(), and ShaderLogF().

Referenced by C4FoW::GetFramebufShader(), C4FoW::GetRenderShader(), and Refresh().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ Initialised()

bool C4Shader::Initialised ( ) const
inline

Definition at line 106 of file C4Shader.h.

107  {
108 #ifndef USE_CONSOLE
109  return hProg != 0;
110 #else
111  return true;
112 #endif
113  }

Referenced by C4LandscapeRenderGL::Draw(), C4FoW::GetFramebufShader(), C4FoW::GetRenderShader(), and StdMeshMaterialProgram::IsCompiled().

Here is the caller graph for this function:

◆ IsLogging()

bool C4Shader::IsLogging ( )
static

Definition at line 665 of file C4Shader.cpp.

665 { return Config.Graphics.DebugOpenGL != 0 || !!Application.isEditor; }
C4Config Config
Definition: C4Config.cpp:930
C4Application Application
Definition: C4Globals.cpp:44
int32_t DebugOpenGL
Definition: C4Config.h:117
C4ConfigGraphics Graphics
Definition: C4Config.h:257

References Application, Config, C4ConfigGraphics::DebugOpenGL, C4Config::Graphics, and C4Application::isEditor.

Referenced by Init(), and OpenExtraLogs().

Here is the caller graph for this function:

◆ LoadFragmentSlices()

bool C4Shader::LoadFragmentSlices ( C4GroupSet pGroupSet,
const char *  szFile 
)

Definition at line 92 of file C4Shader.cpp.

93 {
94  return LoadSlices(FragmentSlices, pGroups, szFile);
95 }

◆ LoadVertexSlices()

bool C4Shader::LoadVertexSlices ( C4GroupSet pGroupSet,
const char *  szFile 
)

Definition at line 97 of file C4Shader.cpp.

98 {
99  return LoadSlices(VertexSlices, pGroups, szFile);
100 }

◆ Refresh()

bool C4Shader::Refresh ( )

Definition at line 445 of file C4Shader.cpp.

446 {
447  // Update last refresh. Keep a local copy around though to identify added script shaders.
448  LastRefresh = C4TimeMilliseconds::Now();
449 
450  auto next = ScriptShader.GetShaderIDs(Categories);
451  std::set<int> toAdd, toRemove;
452  std::set_difference(ScriptShaders.begin(), ScriptShaders.end(), next.begin(), next.end(), std::inserter(toRemove, toRemove.end()));
453  std::set_difference(next.begin(), next.end(), ScriptShaders.begin(), ScriptShaders.end(), std::inserter(toAdd, toAdd.end()));
454  ScriptShaders = next;
455 
456  auto removeSlices = [&](ShaderSliceList::iterator& pSlice)
457  {
458  StdCopyStrBuf Source = pSlice->Source;
459 
460  // Okay, remove all slices that came from this file
461  ShaderSliceList::iterator pNext;
462  for (; pSlice != FragmentSlices.end(); pSlice = pNext)
463  {
464  pNext = pSlice; pNext++;
465  if (SEqual(pSlice->Source.getData(), Source.getData()))
466  FragmentSlices.erase(pSlice);
467  }
468  };
469 
470  // Find slices where the source file has updated.
471  std::vector<StdCopyStrBuf> sourcesToUpdate;
472  for (ShaderSliceList::iterator pSlice = FragmentSlices.begin(); pSlice != FragmentSlices.end(); pSlice++)
473  if (pSlice->Source.getLength())
474  {
475  if (pSlice->Source.BeginsWith("[script "))
476  {
477  // TODO: Maybe save id instead of parsing the string here.
478  int sid = -1;
479  sscanf(pSlice->Source.getData(), "[script %d", &sid);
480  if (toRemove.find(sid) != toRemove.end())
481  removeSlices(pSlice);
482  // Note: script slices don't change, so we don't have to handle updates like for files.
483  }
484  else if (FileExists(pSlice->Source.getData()) &&
485  FileTime(pSlice->Source.getData()) > pSlice->SourceTime)
486  {
487  sourcesToUpdate.push_back(pSlice->Source);
488  removeSlices(pSlice);
489  }
490  }
491 
492  // Anything to do?
493  if (toAdd.size() == 0 && toRemove.size() == 0 && sourcesToUpdate.size() == 0)
494  return true;
495 
496  // Process file reloading.
497  for (auto& Source : sourcesToUpdate)
498  {
499  char szParentPath[_MAX_PATH_LEN]; C4Group Group;
500  StdStrBuf Shader;
501  GetParentPath(Source.getData(),szParentPath);
502  if(!Group.Open(szParentPath) ||
503  !Group.LoadEntryString(GetFilename(Source.getData()),&Shader) ||
504  !Group.Close())
505  {
506  ShaderLogF(" gl: Failed to refresh %s shader from %s!", Name.getData(), Source.getData());
507  return false;
508  }
509 
510  // Load slices
511  int iSourceTime = FileTime(Source.getData());
512  StdStrBuf WhatSrc = FormatString("file %s", Config.AtRelativePath(Source.getData()));
513  AddFragmentSlices(WhatSrc.getData(), Shader.getData(), Source.getData(), iSourceTime);
514  }
515 
516  // Process new script slices.
517  for (int id : toAdd)
518  {
519  LoadScriptSlice(id);
520  }
521 
522 #ifndef USE_CONSOLE
523  std::vector<const char*> UniformNames(Uniforms.size() + 1);
524  for (std::size_t i = 0; i < Uniforms.size(); ++i)
525  UniformNames[i] = Uniforms[i].name;
526  UniformNames[Uniforms.size()] = nullptr;
527 
528  std::vector<const char*> AttributeNames(Attributes.size() + 1);
529  for (std::size_t i = 0; i < Attributes.size(); ++i)
530  AttributeNames[i] = Attributes[i].name;
531  AttributeNames[Attributes.size()] = nullptr;
532 #endif
533 
534  // Reinitialise
535  StdCopyStrBuf What(Name);
536  if (!Init(What.getData(),
537 #ifndef USE_CONSOLE
538  &UniformNames[0],
539  &AttributeNames[0]
540 #else
541  nullptr,
542  nullptr
543 #endif
544  ))
545  return false;
546 
547  return true;
548 }
C4ScriptShader ScriptShader
Definition: C4Shader.cpp:719
#define _MAX_PATH_LEN
bool SEqual(const char *szStr1, const char *szStr2)
Definition: Standard.h:93
bool GetParentPath(const char *szFilename, char *szBuffer)
Definition: StdFile.cpp:186
char * GetFilename(char *szPath)
Definition: StdFile.cpp:42
int FileTime(const char *fname)
bool FileExists(const char *szFileName)
const char * AtRelativePath(const char *filename)
Definition: C4Config.cpp:741
bool LoadEntryString(const char *entry_name, StdStrBuf *buffer)
Definition: C4Group.cpp:2430
bool Close()
Definition: C4Group.cpp:971
bool Open(const char *group_name, bool do_create=false)
Definition: C4Group.cpp:660
std::set< int > GetShaderIDs(const std::vector< std::string > &cats)
Definition: C4Shader.cpp:721
bool Init(const char *szWhat, const char **szUniforms, const char **szAttributes)
Definition: C4Shader.cpp:348
void AddFragmentSlices(const char *szWhat, const char *szText, const char *szSource="", int iFileTime=0)
Definition: C4Shader.cpp:87

References _MAX_PATH_LEN, AddFragmentSlices(), C4Config::AtRelativePath(), C4Group::Close(), Config, FileExists(), FileTime(), FormatString(), StdStrBuf::getData(), GetFilename(), GetParentPath(), C4ScriptShader::GetShaderIDs(), Init(), C4Group::LoadEntryString(), C4TimeMilliseconds::Now(), C4Group::Open(), ScriptShader, SEqual(), and ShaderLogF().

Here is the call graph for this function:

◆ SetScriptCategories()

void C4Shader::SetScriptCategories ( const std::vector< std::string > &  categories)

Definition at line 102 of file C4Shader.cpp.

103 {
104  assert(!ScriptSlicesLoaded && "Can't change shader categories after initialization");
105  Categories = categories;
106 }

Friends And Related Function Documentation

◆ C4ScriptUniform

friend class C4ScriptUniform
friend

Definition at line 64 of file C4Shader.h.

◆ C4ShaderCall

friend class C4ShaderCall
friend

Definition at line 63 of file C4Shader.h.


The documentation for this class was generated from the following files: