xoreos  0.0.5
shadermaterial.cpp
Go to the documentation of this file.
1 /* xoreos - A reimplementation of BioWare's Aurora engine
2  *
3  * xoreos is the legal property of its developers, whose names
4  * can be found in the AUTHORS file distributed with this source
5  * distribution.
6  *
7  * xoreos is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 3
10  * of the License, or (at your option) any later version.
11  *
12  * xoreos is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with xoreos. If not, see <http://www.gnu.org/licenses/>.
19  */
20 
26 
27 namespace Graphics {
28 
29 namespace Shader {
30 
31 #define SHADER_MATERIAL_VARIABLE_OWNED (0x00000001)
32 
33 ShaderMaterial::ShaderMaterial(Shader::ShaderObject *fragShader, const Common::UString &name) : _variableData(), _fragShader(fragShader), _flags(0), _name(name), _usageCount(0), _alphaIndex(0xFFFFFFFF) {
34  fragShader->usageCount++;
35 
36  uint32 varCount = fragShader->variablesCombined.size();
37  _variableData.resize(varCount);
38  for (uint32 i = 0; i < varCount; ++i) {
39  _variableData[i].flags = 0;
40  genMaterialVar(i);
41 
42  if (fragShader->variablesCombined[i].name == "_alpha") {
43  _alphaIndex = i;
44  }
45  }
46  this->recalcTextureUnits();
47 }
48 
50  for (uint32 i = 0; i < _variableData.size(); ++i) {
51  delMaterialVar(i);
52  }
53 }
54 
56  return _name;
57 }
58 
60  return _flags;
61 }
62 
64  _flags = flags;
65 }
66 
68  return _fragShader;
69 }
70 
72  return _fragShader->variablesCombined.size();
73  // return _variableData.size(); // Should be equal to the frag shader variable count.
74 }
75 
77  return _fragShader->variablesCombined[index].type;
78 }
79 
81  return _variableData[index].data;
82 }
83 
85  void *rval = 0;
86 
87  for (uint32 i = 0; i < _variableData.size(); ++i) {
88  if (_fragShader->variablesCombined[i].name == name) {
89  rval = _variableData[i].data;
90  break;
91  }
92  }
93 
94  return rval;
95 }
96 
98  return _fragShader->variablesCombined[index].name;
99 }
100 
102  return _variableData[index].flags;
103 }
104 
105 void ShaderMaterial::setVariableExternal(uint32 index, void *loc, bool textureUnitRecalc) {
106  delMaterialVar(index);
107  _variableData[index].data = loc;
108  if (textureUnitRecalc) {
110  }
111 }
112 
113 void ShaderMaterial::setVariableExternal(const Common::UString &name, void *loc, bool textureUnitRecalc) {
114  for (uint32 i = 0; i < _variableData.size(); ++i) {
115  if (_fragShader->variablesCombined[i].name == name) {
116  delMaterialVar(i);
117  _variableData[i].data = loc;
118  break;
119  }
120  }
121 
122  if (textureUnitRecalc) {
124  }
125 }
126 
127 void ShaderMaterial::setVariableInternal(uint32 index, bool textureUnitRecalc) {
128  genMaterialVar(index);
129 
130  if (textureUnitRecalc) {
132  }
133 }
134 
135 void ShaderMaterial::setVariableInternal(const Common::UString &name, bool textureUnitRecalc) {
136  for (uint32 i = 0; i < _variableData.size(); ++i) {
137  if (_fragShader->variablesCombined[i].name == name) {
138  genMaterialVar(i);
139  break;
140  }
141  }
142 
143  if (textureUnitRecalc) {
145  }
146 }
147 
149  uint32 unit = 0;
150 
151  // First iterate through and find all external variables - they have master control over texture unit assignment.
152  for (uint32 i = 0; i < _variableData.size(); ++i) {
153  switch (_fragShader->variablesCombined[i].type) {
154  case SHADER_SAMPLER1D:
155  case SHADER_SAMPLER2D:
156  case SHADER_SAMPLER3D:
157  case SHADER_SAMPLERCUBE:
158  if (!(_variableData[i].flags & SHADER_MATERIAL_VARIABLE_OWNED)) {
159  unit |= (1 << (static_cast<Shader::ShaderSampler *>(_variableData[i].data)->unit));
160  }
161  break;
162  default: break;
163  }
164  }
165 
166  // Now fill in the gaps.
167  for (uint32 i = 0; i < _variableData.size(); ++i) {
168  switch (_fragShader->variablesCombined[i].type) {
169  case SHADER_SAMPLER1D:
170  case SHADER_SAMPLER2D:
171  case SHADER_SAMPLER3D:
172  case SHADER_SAMPLERCUBE:
174  uint32 textureUnit = 0;
175  for (uint32 j = 1; j < 0x80000000; j<<=1, ++textureUnit)
176  {
177  if (!(unit & j)) {
178  unit |= j;
179  break;
180  }
181  }
182  static_cast<Shader::ShaderSampler *>(_variableData[i].data)->unit = textureUnit;
183  }
184  break;
185  default: break;
186  }
187  }
188 }
189 
191  return (_variableData[index].flags & SHADER_MATERIAL_VARIABLE_OWNED) ? true : false;
192 }
193 
195  bool rval = false;
196  for (uint32 i = 0; i < _variableData.size(); ++i) {
197  if (_fragShader->variablesCombined[i].name == name) {
198  rval = (_variableData[i].flags & SHADER_MATERIAL_VARIABLE_OWNED) ? true : false;
199  break;
200  }
201  }
202 
203  return rval;
204 }
205 
207  for (uint32 i = 0; i < _variableData.size(); i++) {
208  ShaderMan.bindShaderVariable(program->fragmentObject->variablesCombined[i], program->fragmentVariableLocations[i], _variableData[i].data);
209  }
210 }
211 
213  for (uint32 i = 0; i < _variableData.size(); i++) {
214  if (_alphaIndex != i) {
215  ShaderMan.bindShaderVariable(program->fragmentObject->variablesCombined[i], program->fragmentVariableLocations[i], _variableData[i].data);
216  }
217  }
218 }
219 
221  for (uint32 i = 0; i < _variableData.size(); i++) {
222  if (_alphaIndex == i) {
223  ShaderMan.bindShaderVariable(program->fragmentObject->variablesCombined[i], program->fragmentVariableLocations[i], &alpha);
224  } else {
225  ShaderMan.bindShaderVariable(program->fragmentObject->variablesCombined[i], program->fragmentVariableLocations[i], _variableData[i].data);
226  }
227  }
228 }
229 
230 void ShaderMaterial::bindFade(Shader::ShaderProgram *program, float alpha) {
231  if (_alphaIndex != 0xFFFFFFFF) {
232  ShaderMan.bindShaderVariable(program->fragmentObject->variablesCombined[_alphaIndex], program->fragmentVariableLocations[_alphaIndex], &alpha);
233  }
234 }
235 
238  glBlendFunc(GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
239  }
240 }
241 
244  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
245  }
246 }
247 
249  glDisable(GL_BLEND);
250  glEnable(GL_CULL_FACE);
251  glEnable(GL_DEPTH_TEST);
252  glDepthMask(GL_TRUE);
253 }
254 
257  return 0;
258 
259  void *rval = 0;
260  uint32 count = _fragShader->variablesCombined[index].count;
261 
262  switch (_fragShader->variablesCombined[index].type) {
263  case SHADER_FLOAT: rval = new float[count]; break;
264  case SHADER_VEC2: rval = new float[2 * count]; break;
265  case SHADER_VEC3: rval = new float[3 * count]; break;
266  case SHADER_VEC4: rval = new float[4 * count]; break;
267  case SHADER_INT: rval = new int[count]; break;
268  case SHADER_IVEC2: rval = new int[2 * count]; break;
269  case SHADER_IVEC3: rval = new int[3 * count]; break;
270  case SHADER_IVEC4: rval = new int[4 * count]; break;
271 // case SHADER_UINT: break;
272 // case SHADER_UVEC2: break;
273 // case SHADER_UVEC3: break;
274 // case SHADER_UVEC4: break;
275 // case SHADER_BOOL: break;
276 // case SHADER_BVEC2: break;
277 // case SHADER_BVEC3: break;
278 // case SHADER_BVEC4: break;
279  case SHADER_MAT2: rval = new float[4 * count]; break;
280  case SHADER_MAT3: rval = new float[9 * count]; break;
281  case SHADER_MAT4: rval = new float[16 * count]; break;
282  case SHADER_SAMPLER1D:
283  case SHADER_SAMPLER2D:
284  case SHADER_SAMPLER3D:
285  case SHADER_SAMPLERCUBE: rval = new Shader::ShaderSampler(); break;
286  case SHADER_SAMPLER1DSHADOW: break;
287  case SHADER_SAMPLER2DSHADOW: break;
288  case SHADER_SAMPLER1DARRAY: break;
289  case SHADER_SAMPLER2DARRAY: break;
290  case SHADER_SAMPLER1DARRAYSHADOW: break;
291  case SHADER_SAMPLER2DARRAYSHADOW: break;
292  case SHADER_SAMPLERBUFFER: break;
293  case SHADER_ISAMPLER1D: break;
294  case SHADER_ISAMPLER2D: break;
295  case SHADER_ISAMPLER3D: break;
296  case SHADER_ISAMPLERCUBE: break;
297  case SHADER_ISAMPLER1DARRAY: break;
298  case SHADER_ISAMPLER2DARRAY: break;
299  case SHADER_USAMPLER1D: break;
300  case SHADER_USAMPLER2D: break;
301  case SHADER_USAMPLER3D: break;
302  case SHADER_USAMPLERCUBE: break;
303  case SHADER_USAMPLER1DARRAY: break;
304  case SHADER_USAMPLER2DARRAY: break;
305  case SHADER_UNIFORM_BUFFER: rval = new Shader::ShaderUBO; break;
306  default: break;
307  }
308 
310  _variableData[index].data = rval;
311 
312  return rval;
313 }
314 
316 {
317  if (!(_variableData[index].flags & SHADER_MATERIAL_VARIABLE_OWNED))
318  return;
319 
321 
322  void *data = _variableData[index].data;
323  switch (_fragShader->variablesCombined[index].type) {
324  case SHADER_FLOAT:
325  case SHADER_VEC2:
326  case SHADER_VEC3:
327  case SHADER_VEC4: delete [] (static_cast<float *>(data)); break;
328  case SHADER_INT:
329  case SHADER_IVEC2:
330  case SHADER_IVEC3:
331  case SHADER_IVEC4: delete [] (static_cast<int *>(data)); break;
332 // case SHADER_UINT: break;
333 // case SHADER_UVEC2: break;
334 // case SHADER_UVEC3: break;
335 // case SHADER_UVEC4: break;
336 // case SHADER_BOOL: break;
337 // case SHADER_BVEC2: break;
338 // case SHADER_BVEC3: break;
339 // case SHADER_BVEC4: break;
340  case SHADER_MAT2:
341  case SHADER_MAT3:
342  case SHADER_MAT4: delete [] (static_cast<float *>(data)); break;
343  case SHADER_SAMPLER1D:
344  case SHADER_SAMPLER2D:
345  case SHADER_SAMPLER3D:
346  case SHADER_SAMPLERCUBE:
347  // todo: link in texture usage count properly here.
348  //if(static_cast<ShaderMaterial::ShaderMaterialSampler *>(data)->texture != 0)
349  // static_cast<ShaderMaterial::ShaderMaterialSampler *>(data)->texture->_usageCount--;
350  delete (static_cast<Shader::ShaderSampler *>(data));
351  break;
352  case SHADER_SAMPLER1DSHADOW: break;
353  case SHADER_SAMPLER2DSHADOW: break;
354  case SHADER_SAMPLER1DARRAY: break;
355  case SHADER_SAMPLER2DARRAY: break;
356  case SHADER_SAMPLER1DARRAYSHADOW: break;
357  case SHADER_SAMPLER2DARRAYSHADOW: break;
358  case SHADER_SAMPLERBUFFER: break;
359  case SHADER_ISAMPLER1D: break;
360  case SHADER_ISAMPLER2D: break;
361  case SHADER_ISAMPLER3D: break;
362  case SHADER_ISAMPLERCUBE: break;
363  case SHADER_ISAMPLER1DARRAY: break;
364  case SHADER_ISAMPLER2DARRAY: break;
365  case SHADER_USAMPLER1D: break;
366  case SHADER_USAMPLER2D: break;
367  case SHADER_USAMPLER3D: break;
368  case SHADER_USAMPLERCUBE: break;
369  case SHADER_USAMPLER1DARRAY: break;
370  case SHADER_USAMPLER2DARRAY: break;
371  case SHADER_UNIFORM_BUFFER: delete static_cast<ShaderUBO *>(data); break;
372  default: break;
373  }
374 
375  _variableData[index].data = 0;
376 }
377 
379  ++_usageCount;
380 }
381 
383  if (_usageCount) {
384  --_usageCount;
385  }
386 }
387 
389  return _usageCount;
390 }
391 
392 } // End of namespace Shader
393 
394 } // End of namespace Graphics
A class holding an UTF-8 string.
Definition: ustring.h:48
bool isVariableOwned(uint32 index) const
Shader::ShaderVariableType getVariableType(uint32 index) const
Shader::ShaderObject * getFragmentShader() const
void * getVariableData(uint32 index) const
ShaderMaterial(Shader::ShaderObject *fragShader, const Common::UString &name="unnamed")
Different to default blending. Maybe this should be extended one day.
void bindFade(Shader::ShaderProgram *program, float fade)
#define SHADER_MATERIAL_VARIABLE_OWNED
ShaderObject * fragmentObject
Definition: shader.h:219
const Common::UString & getName() const
Shader material, responsible for tracking data relating to a fragment shader.
ShaderVariableType
Enum of all supported shader variable parsing and automatic binding.
Definition: shader.h:85
Shader::ShaderObject * _fragShader
std::vector< GLint > fragmentVariableLocations
Definition: shader.h:221
void * genMaterialVar(uint32 index)
void bindProgram(Shader::ShaderProgram *program)
Shader sampler is used to bind a texture to a texture unit.
Definition: shader.h:174
#define ShaderMan
Shortcut for accessing the shader manager.
Definition: shader.h:293
uint32_t uint32
Definition: types.h:204
void bindProgramNoFade(Shader::ShaderProgram *program)
void setVariableExternal(uint32 index, void *loc, bool textureUnitRecalc=true)
const Common::UString & getVariableName(uint32 index) const
std::vector< ShaderMaterialVariable > _variableData
void setVariableInternal(uint32 index, bool textureUnitRecalc=true)
std::vector< ShaderObject::ShaderObjectVariable > variablesCombined
Definition: shader.h:206
uint32 getVariableFlags(uint32 index) const