OpenClonk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros
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 62 of file C4Shader.h.

Constructor & Destructor Documentation

C4Shader::C4Shader ( )

Definition at line 45 of file C4Shader.cpp.

46  : iTexCoords(0)
47  , LastRefresh()
48 #ifndef USE_CONSOLE
49  , hProg(0)
50 #endif
51 {
52 
53 }
C4Shader::~C4Shader ( )

Definition at line 55 of file C4Shader.cpp.

References Clear().

56 {
57  Clear();
58 }
void Clear()
Definition: C4Shader.cpp:337

Here is the call graph for this function:

Member Function Documentation

void C4Shader::AddDefine ( const char *  name)

Definition at line 67 of file C4Shader.cpp.

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

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

68 {
69  StdStrBuf define = FormatString("#define %s", name);
70  AddVertexSlice(-1, define.getData());
71  AddFragmentSlice(-1, define.getData());
72 }
const char * getData() const
Definition: StdBuf.h:450
void AddFragmentSlice(int iPos, const char *szText)
Definition: C4Shader.cpp:79
void AddVertexSlice(int iPos, const char *szText)
Definition: C4Shader.cpp:74
StdStrBuf FormatString(const char *szFmt,...)
Definition: StdBuf.cpp:277

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 79 of file C4Shader.cpp.

Referenced by AddDefine().

80 {
81  AddSlice(FragmentSlices, iPos, szText, nullptr, 0, 0);
82 }

Here is the caller graph for this function:

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

Definition at line 89 of file C4Shader.cpp.

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

90 {
91  AddSlices(FragmentSlices, szWhat, szText, szSource, iSourceTime);
92 }

Here is the caller graph for this function:

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

Definition at line 74 of file C4Shader.cpp.

Referenced by AddDefine().

75 {
76  AddSlice(VertexSlices, iPos, szText, nullptr, 0, 0);
77 }

Here is the caller graph for this function:

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

Definition at line 84 of file C4Shader.cpp.

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

85 {
86  AddSlices(VertexSlices, szWhat, szText, szSource, iSourceTime);
87 }

Here is the caller graph for this function:

void C4Shader::Clear ( )

Definition at line 337 of file C4Shader.cpp.

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

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

Here is the caller graph for this function:

void C4Shader::ClearSlices ( )

Definition at line 326 of file C4Shader.cpp.

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

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

Here is the caller graph for this function:

GLint C4Shader::GetAttribute ( int  iAttribute) const
inline

Definition at line 128 of file C4Shader.h.

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

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

Here is the caller graph for this function:

GLint C4Shader::GetUniform ( int  iUniform) const
inline
bool C4Shader::HaveUniform ( int  iUniform) const
inline

Definition at line 123 of file C4Shader.h.

References GetUniform().

Referenced by C4ShaderCall::AllocTexUnit(), C4LandscapeRenderGL::Draw(), C4ShaderCall::SetUniform1f(), C4ShaderCall::SetUniform1fv(), C4ShaderCall::SetUniform1i(), C4ShaderCall::SetUniform1iv(), C4ShaderCall::SetUniform2f(), C4ShaderCall::SetUniform2fv(), C4ShaderCall::SetUniform3fv(), C4ShaderCall::SetUniform4fv(), C4ShaderCall::SetUniformMatrix2x3fv(), C4ShaderCall::SetUniformMatrix3x3(), C4ShaderCall::SetUniformMatrix3x3fv(), C4ShaderCall::SetUniformMatrix3x3Transpose(), C4ShaderCall::SetUniformMatrix3x4(), C4ShaderCall::SetUniformMatrix3x4fv(), C4ShaderCall::SetUniformMatrix4x4(), and C4ShaderCall::SetUniformMatrix4x4fv().

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

Here is the call graph for this function:

Here is the caller graph for this function:

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

Definition at line 350 of file C4Shader.cpp.

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

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

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

Here is the call graph for this function:

Here is the caller graph for this function:

bool C4Shader::Initialised ( ) const
inline

Definition at line 107 of file C4Shader.h.

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

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

Here is the caller graph for this function:

bool C4Shader::IsLogging ( )
static

Definition at line 667 of file C4Shader.cpp.

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

Referenced by Init(), and OpenExtraLogs().

667 { return Config.Graphics.DebugOpenGL != 0 || !!Application.isEditor; }
int32_t DebugOpenGL
Definition: C4Config.h:118
C4Config Config
Definition: C4Config.cpp:831
C4ConfigGraphics Graphics
Definition: C4Config.h:254
C4Application Application
Definition: C4Globals.cpp:44

Here is the caller graph for this function:

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

Definition at line 94 of file C4Shader.cpp.

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

95 {
96  return LoadSlices(FragmentSlices, pGroups, szFile);
97 }

Here is the caller graph for this function:

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

Definition at line 99 of file C4Shader.cpp.

Referenced by CStdGL::PrepareSpriteShader().

100 {
101  return LoadSlices(VertexSlices, pGroups, szFile);
102 }

Here is the caller graph for this function:

bool C4Shader::Refresh ( )

Definition at line 447 of file C4Shader.cpp.

References _MAX_PATH, 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().

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

Here is the call graph for this function:

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

Definition at line 104 of file C4Shader.cpp.

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

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

Here is the caller graph for this function:

Friends And Related Function Documentation

friend class C4ScriptUniform
friend

Definition at line 65 of file C4Shader.h.

friend class C4ShaderCall
friend

Definition at line 64 of file C4Shader.h.


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