1 /*=========================================================================
2 
3   Program:   Visualization Toolkit
4   Module:    vtkShaderProperty.cxx
5 
6   Copyright (c) Ken Martin, Will Schroeder, Bill Lorensen
7   All rights reserved.
8   See Copyright.txt or http://www.kitware.com/Copyright.htm for details.
9 
10      This software is distributed WITHOUT ANY WARRANTY; without even
11      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
12      PURPOSE.  See the above copyright notice for more information.
13 
14 =========================================================================*/
15 #include "vtkOpenGLShaderProperty.h"
16 
17 #include "vtkObjectFactory.h"
18 #include "vtkOpenGLUniforms.h"
19 #include <algorithm>
20 
21 vtkStandardNewMacro(vtkOpenGLShaderProperty);
22 
23 vtkOpenGLShaderProperty::vtkOpenGLShaderProperty() = default;
24 
25 vtkOpenGLShaderProperty::~vtkOpenGLShaderProperty() = default;
26 
DeepCopy(vtkOpenGLShaderProperty * p)27 void vtkOpenGLShaderProperty::DeepCopy(vtkOpenGLShaderProperty* p)
28 {
29   vtkShaderProperty::DeepCopy(p);
30   this->UserShaderReplacements = p->UserShaderReplacements;
31 }
32 
AddVertexShaderReplacement(const std::string & originalValue,bool replaceFirst,const std::string & replacementValue,bool replaceAll)33 void vtkOpenGLShaderProperty::AddVertexShaderReplacement(const std::string& originalValue,
34   bool replaceFirst, // do this replacement before the default
35   const std::string& replacementValue, bool replaceAll)
36 {
37   this->AddShaderReplacement(
38     vtkShader::Vertex, originalValue, replaceFirst, replacementValue, replaceAll);
39 }
40 
AddFragmentShaderReplacement(const std::string & originalValue,bool replaceFirst,const std::string & replacementValue,bool replaceAll)41 void vtkOpenGLShaderProperty::AddFragmentShaderReplacement(const std::string& originalValue,
42   bool replaceFirst, // do this replacement before the default
43   const std::string& replacementValue, bool replaceAll)
44 {
45   this->AddShaderReplacement(
46     vtkShader::Fragment, originalValue, replaceFirst, replacementValue, replaceAll);
47 }
48 
AddGeometryShaderReplacement(const std::string & originalValue,bool replaceFirst,const std::string & replacementValue,bool replaceAll)49 void vtkOpenGLShaderProperty::AddGeometryShaderReplacement(const std::string& originalValue,
50   bool replaceFirst, // do this replacement before the default
51   const std::string& replacementValue, bool replaceAll)
52 {
53   this->AddShaderReplacement(
54     vtkShader::Geometry, originalValue, replaceFirst, replacementValue, replaceAll);
55 }
56 
GetNumberOfShaderReplacements()57 int vtkOpenGLShaderProperty::GetNumberOfShaderReplacements()
58 {
59   return static_cast<int>(UserShaderReplacements.size());
60 }
61 
GetNthShaderReplacementTypeAsString(vtkIdType index)62 std::string vtkOpenGLShaderProperty::GetNthShaderReplacementTypeAsString(vtkIdType index)
63 {
64   if (index >= static_cast<vtkIdType>(this->UserShaderReplacements.size()))
65   {
66     vtkErrorMacro(<< "Trying to access out of bound shader replacement.");
67     return std::string("");
68   }
69   ReplacementMap::iterator it = this->UserShaderReplacements.begin();
70   std::advance(it, index);
71   if (it->first.ShaderType == vtkShader::Vertex)
72   {
73     return std::string("Vertex");
74   }
75   else if (it->first.ShaderType == vtkShader::Fragment)
76   {
77     return std::string("Fragment");
78   }
79   else if (it->first.ShaderType == vtkShader::Geometry)
80   {
81     return std::string("Geometry");
82   }
83   return std::string("Unknown");
84 }
85 
GetNthShaderReplacement(vtkIdType index,std::string & name,bool & replaceFirst,std::string & replacementValue,bool & replaceAll)86 void vtkOpenGLShaderProperty::GetNthShaderReplacement(vtkIdType index, std::string& name,
87   bool& replaceFirst, std::string& replacementValue, bool& replaceAll)
88 {
89   if (index >= static_cast<vtkIdType>(this->UserShaderReplacements.size()))
90   {
91     vtkErrorMacro(<< "Trying to access out of bound shader replacement.");
92   }
93   ReplacementMap::iterator it = this->UserShaderReplacements.begin();
94   std::advance(it, index);
95   name = it->first.OriginalValue;
96   replaceFirst = it->first.ReplaceFirst;
97   replacementValue = it->second.Replacement;
98   replaceAll = it->second.ReplaceAll;
99 }
100 
ClearVertexShaderReplacement(const std::string & originalValue,bool replaceFirst)101 void vtkOpenGLShaderProperty::ClearVertexShaderReplacement(
102   const std::string& originalValue, bool replaceFirst)
103 {
104   this->ClearShaderReplacement(vtkShader::Vertex, originalValue, replaceFirst);
105 }
106 
ClearFragmentShaderReplacement(const std::string & originalValue,bool replaceFirst)107 void vtkOpenGLShaderProperty::ClearFragmentShaderReplacement(
108   const std::string& originalValue, bool replaceFirst)
109 {
110   this->ClearShaderReplacement(vtkShader::Fragment, originalValue, replaceFirst);
111 }
112 
ClearGeometryShaderReplacement(const std::string & originalValue,bool replaceFirst)113 void vtkOpenGLShaderProperty::ClearGeometryShaderReplacement(
114   const std::string& originalValue, bool replaceFirst)
115 {
116   this->ClearShaderReplacement(vtkShader::Geometry, originalValue, replaceFirst);
117 }
118 
ClearAllVertexShaderReplacements()119 void vtkOpenGLShaderProperty::ClearAllVertexShaderReplacements()
120 {
121   this->ClearAllShaderReplacements(vtkShader::Vertex);
122 }
123 
ClearAllFragmentShaderReplacements()124 void vtkOpenGLShaderProperty::ClearAllFragmentShaderReplacements()
125 {
126   this->ClearAllShaderReplacements(vtkShader::Fragment);
127 }
128 
ClearAllGeometryShaderReplacements()129 void vtkOpenGLShaderProperty::ClearAllGeometryShaderReplacements()
130 {
131   this->ClearAllShaderReplacements(vtkShader::Geometry);
132 }
133 
134 //------------------------------------------------------------------------------
ClearAllShaderReplacements()135 void vtkOpenGLShaderProperty::ClearAllShaderReplacements()
136 {
137   this->SetVertexShaderCode(nullptr);
138   this->SetFragmentShaderCode(nullptr);
139   this->SetGeometryShaderCode(nullptr);
140   this->UserShaderReplacements.clear();
141   this->Modified();
142 }
143 
144 //------------------------------------------------------------------------------
AddShaderReplacement(vtkShader::Type shaderType,const std::string & originalValue,bool replaceFirst,const std::string & replacementValue,bool replaceAll)145 void vtkOpenGLShaderProperty::AddShaderReplacement(
146   vtkShader::Type shaderType, // vertex, fragment, etc
147   const std::string& originalValue,
148   bool replaceFirst, // do this replacement before the default
149   const std::string& replacementValue, bool replaceAll)
150 {
151   vtkShader::ReplacementSpec spec;
152   spec.ShaderType = shaderType;
153   spec.OriginalValue = originalValue;
154   spec.ReplaceFirst = replaceFirst;
155 
156   vtkShader::ReplacementValue values;
157   values.Replacement = replacementValue;
158   values.ReplaceAll = replaceAll;
159 
160   this->UserShaderReplacements[spec] = values;
161   this->Modified();
162 }
163 
164 //------------------------------------------------------------------------------
ClearShaderReplacement(vtkShader::Type shaderType,const std::string & originalValue,bool replaceFirst)165 void vtkOpenGLShaderProperty::ClearShaderReplacement(
166   vtkShader::Type shaderType, // vertex, fragment, etc
167   const std::string& originalValue, bool replaceFirst)
168 {
169   vtkShader::ReplacementSpec spec;
170   spec.ShaderType = shaderType;
171   spec.OriginalValue = originalValue;
172   spec.ReplaceFirst = replaceFirst;
173 
174   typedef std::map<vtkShader::ReplacementSpec, vtkShader::ReplacementValue>::iterator RIter;
175   RIter found = this->UserShaderReplacements.find(spec);
176   if (found != this->UserShaderReplacements.end())
177   {
178     this->UserShaderReplacements.erase(found);
179     this->Modified();
180   }
181 }
182 
183 //------------------------------------------------------------------------------
ClearAllShaderReplacements(vtkShader::Type shaderType)184 void vtkOpenGLShaderProperty::ClearAllShaderReplacements(vtkShader::Type shaderType)
185 {
186   bool modified = false;
187   // First clear all shader code
188   if ((shaderType == vtkShader::Vertex) && this->VertexShaderCode)
189   {
190     this->SetVertexShaderCode(nullptr);
191     modified = true;
192   }
193   else if ((shaderType == vtkShader::Fragment) && this->FragmentShaderCode)
194   {
195     this->SetFragmentShaderCode(nullptr);
196     modified = true;
197   }
198 
199   // Now clear custom tag replacements
200   std::map<vtkShader::ReplacementSpec, vtkShader::ReplacementValue>::iterator rIter;
201   for (rIter = this->UserShaderReplacements.begin(); rIter != this->UserShaderReplacements.end();)
202   {
203     if (rIter->first.ShaderType == shaderType)
204     {
205       this->UserShaderReplacements.erase(rIter++);
206       modified = true;
207     }
208     else
209     {
210       ++rIter;
211     }
212   }
213   if (modified)
214   {
215     this->Modified();
216   }
217 }
218 
219 //------------------------------------------------------------------------------
PrintSelf(ostream & os,vtkIndent indent)220 void vtkOpenGLShaderProperty::PrintSelf(ostream& os, vtkIndent indent)
221 {
222   this->Superclass::PrintSelf(os, indent);
223 }
224