zenilib  0.5.3.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
Shader.cpp
Go to the documentation of this file.
1 /* This file is part of the Zenipex Library (zenilib).
2  * Copyright (C) 2011 Mitchell Keith Bloch (bazald).
3  *
4  * zenilib is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * zenilib is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with zenilib. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #include <zeni_graphics.h>
19 
20 #ifndef DISABLE_DX9
21 #include <d3dx9shader.h>
22 #endif
23 
24 #include <iostream>
25 
26 namespace Zeni {
27 
28 #ifndef DISABLE_GL_FIXED
29  Shader_GL_Fixed::Shader_GL_Fixed(const String &shader_src, const Type &type)
31  {
32  const char * src_ptr = shader_src.c_str();
33  glShaderSourceARB(m_shader, 1, reinterpret_cast<const GLchar **>(&src_ptr), 0);
34  if(!m_shader)
35  throw Shader_Init_Failure();
36  glCompileShaderARB(m_shader);
37  }
38 
40  glDeleteShader(m_shader);
41  }
42 
44  : m_program(glCreateProgram())
45  {
46  }
47 
49  for(std::list<Shader_GL_Fixed *>::iterator it = m_shaders.begin(), iend = m_shaders.end(); it != iend; ++it)
50  glDetachShader(m_program, (*it)->get());
51  m_shaders.clear();
52 
53  glDeleteProgram(m_program);
54  }
55 
57  Shader_GL_Fixed &shader_gl_fixed = dynamic_cast<Shader_GL_Fixed &>(shader);
58  m_shaders.push_back(&shader_gl_fixed);
59  glAttachShader(m_program, shader_gl_fixed.get());
60  }
61 
63  glLinkProgramARB(m_program);
64 
65  GLint rv = GL_TRUE;
66  glGetProgramivARB(m_program, GL_LINK_STATUS, &rv);
67  if(rv != GL_TRUE)
68  throw Shader_Link_Failure();
69  }
70 #endif
71 
72 #ifndef DISABLE_GL_SHADER
73  Shader_GL_Shader::Shader_GL_Shader(const String &shader_src, const Type &type)
74  : m_shader(glCreateShader(type == VERTEX ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER))
75  {
76  const char * src_ptr = shader_src.c_str();
77  glShaderSource(m_shader, 1, reinterpret_cast<const GLchar **>(&src_ptr), 0);
78  if(!m_shader)
79  throw Shader_Init_Failure();
80  glCompileShader(m_shader);
81 
82  // Check vertex shader
83  GLint rv = GL_TRUE, len;
84  glGetShaderiv(m_shader, GL_COMPILE_STATUS, &rv);
85  if(rv != GL_TRUE) {
86  glGetShaderiv(m_shader, GL_INFO_LOG_LENGTH, &len);
87  Zeni::String log(len > 0 ? len - 1 : 0, '\0');
88  glGetShaderInfoLog(m_shader, len, 0, reinterpret_cast<GLchar *>(const_cast<char *>(log.c_str())));
89  std::cerr << "Shader initialization failure: " << log << std::endl;
90  throw Shader_Init_Failure();
91  }
92  }
93 
95  glDeleteShader(m_shader);
96  }
97 
99  : m_program(glCreateProgram())
100  {
101  }
102 
104  for(std::list<Shader_GL_Shader *>::iterator it = m_shaders.begin(), iend = m_shaders.end(); it != iend; ++it)
105  glDetachShader(m_program, (*it)->get());
106  m_shaders.clear();
107 
108  glDeleteProgram(m_program);
109  }
110 
112  Shader_GL_Shader &shader_gl_shader = dynamic_cast<Shader_GL_Shader &>(shader);
113  m_shaders.push_back(&shader_gl_shader);
114  glAttachShader(m_program, shader_gl_shader.get());
115  }
116 
118  glLinkProgram(m_program);
119 
120  GLint rv = GL_TRUE, len;
121  glGetProgramiv(m_program, GL_LINK_STATUS, &rv);
122  if(rv != GL_TRUE) {
123  glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &len);
124  Zeni::String log(len > 0 ? len - 1 : 0, '\0');
125  glGetProgramInfoLog(m_program, len, 0, reinterpret_cast<GLchar *>(const_cast<char *>(log.c_str())));
126  std::cerr << "Shader link failure: " << log << std::endl;
127  throw Shader_Link_Failure();
128  }
129  }
130 #endif
131 
132 #ifndef DISABLE_DX9
133  Shader_DX9::Shader_DX9(const String &shader_src, const Type &type, Video_DX9 &vdx)
134  : m_constant_table(0),
135  m_vertex_shader(0)
136  {
137  String shader_src_full = shader_src;
138  if(type == VERTEX) {
139  String uniforms;
140  int pos, pos2;
141 
142  pos = shader_src_full.find("// Attributes");
143  shader_src_full = shader_src_full.substr(0, pos) + "struct VS_INPUT {" + shader_src_full.substr(pos + 13);
144  pos = shader_src_full.find("// Varyings");
145  shader_src_full = shader_src_full.substr(0, pos) + "};\nstruct VS_OUTPUT {\nfloat4 gl_Position : POSITION;" + shader_src_full.substr(pos + 11);
146  pos = shader_src_full.rfind("static");
147  pos = shader_src_full.find(';', pos);
148  shader_src_full = shader_src_full.substr(0, pos + 1) + "\n}; " + shader_src_full.substr(pos + 1);
149  pos = shader_src_full.find("static float4 gl_Position");
150  pos2 = shader_src_full.find(';', pos);
151  shader_src_full = shader_src_full.substr(0, pos) + shader_src_full.substr(pos2 + 1);
152 
153  std::set<String> ins;
154  std::set<String> outs;
155  outs.insert("gl_Position");
156 
157  for(pos2 = shader_src_full.find("uniform ");; pos2 = pos) {
158  pos = shader_src_full.rfind(" = ", pos2);
159  if(pos == String::npos)
160  break;
161  pos2 = shader_src_full.find(';', pos);
162  shader_src_full = shader_src_full.substr(0, pos) + shader_src_full.substr(pos2);
163  }
164  for(pos = 0;;) {
165  pos = shader_src_full.find("static ", pos);
166  if(pos == String::npos)
167  break;
168  pos = shader_src_full.find(' ', pos + 7) + 1;
169  pos2 = shader_src_full.find(';', pos);
170  if(shader_src_full.rfind("VS_OUTPUT", pos) != String::npos)
171  outs.insert(shader_src_full.substr(pos, pos2 - pos));
172  else
173  ins.insert(shader_src_full.substr(pos, pos2 - pos));
174  pos = pos2;
175  }
176  for(pos = 0;;) {
177  pos = shader_src_full.find("static ", pos);
178  if(pos == String::npos)
179  break;
180  pos2 = shader_src_full.find(';', pos);
181  String sub = shader_src_full.substr(pos + 7, pos2 - (pos + 7));
182  if(sub.find("position") != String::npos)
183  sub = " : POSITION";
184  else if(sub.find("color") != String::npos)
185  sub = " : COLOR";
186  else
187  sub.clear();
188  shader_src_full = shader_src_full.substr(0, pos) + shader_src_full.substr(pos + 7, pos2 - (pos + 7))
189  + sub + shader_src_full.substr(pos2);
190  }
191  for(pos = 0;;) {
192  pos = shader_src_full.find("uniform ", pos);
193  if(pos == String::npos)
194  break;
195  pos2 = shader_src_full.find(": register(", pos);
196  uniforms += ", " + shader_src_full.substr(pos, pos2 - pos);
197  shader_src_full = shader_src_full.substr(0, pos) + shader_src_full.substr(pos2 + 14);
198  }
199 
200  pos = shader_src_full.find("void gl_main()");
201  pos2 = shader_src_full.find('{', pos) + 1;
202  for(int count = 1; count; ++pos2) {
203  if(shader_src_full[pos2] == '}')
204  --count;
205  else if(shader_src_full[pos2] == '{')
206  ++count;
207  }
208  String shader_front = shader_src_full.substr(0, pos);
209  String shader_back = shader_src_full.substr(pos2 + 1);
210  String main_body = shader_src_full.substr(pos + 14, (pos2 + 1) - (pos + 14));
211 
212  for(std::set<String>::iterator it = ins.begin(), iend = ins.end(); it != iend; ++it) {
213  for(pos = main_body.size();;) {
214  pos = main_body.rfind(*it, pos);
215  if(pos == String::npos)
216  break;
217  main_body = main_body.substr(0, pos) + "v." + main_body.substr(pos);
218  }
219  }
220  for(std::set<String>::iterator it = outs.begin(), iend = outs.end(); it != iend; ++it) {
221  for(pos = main_body.size();;) {
222  pos = main_body.rfind(*it, pos);
223  if(pos == String::npos)
224  break;
225  main_body = main_body.substr(0, pos) + "o." + main_body.substr(pos);
226  }
227  }
228 
229  shader_src_full = shader_front + "VS_OUTPUT vs_main(const VS_INPUT v" + uniforms + ") {VS_OUTPUT o; " + main_body + "return o;}";
230  }
231  else {
232  String uniforms;
233  int pos, pos2;
234 
235  pos = shader_src_full.find("// Varyings");
236  shader_src_full = shader_src_full.substr(0, pos) + "struct PS_INPUT {\nfloat4 gl_Position : POSITION;" + shader_src_full.substr(pos + 11);
237  pos = shader_src_full.rfind("static");
238  pos = shader_src_full.find(';', pos);
239  shader_src_full = shader_src_full.substr(0, pos + 1) + "\n}; " + shader_src_full.substr(pos + 1);
240  pos = shader_src_full.find("static float4 gl_Color[1]");
241  pos2 = shader_src_full.find(';', pos);
242  shader_src_full = shader_src_full.substr(0, pos) + shader_src_full.substr(pos2 + 1);
243 
244  std::set<String> ins;
245 
246  for(pos2 = shader_src_full.find("#define GL_USES_FRAG_COLOR");; pos2 = pos) {
247  pos = shader_src_full.rfind(" = ", pos2);
248  if(pos == String::npos)
249  break;
250  pos2 = shader_src_full.find(';', pos);
251  shader_src_full = shader_src_full.substr(0, pos) + shader_src_full.substr(pos2);
252  }
253  for(pos = 0;;) {
254  pos = shader_src_full.find("static ", pos);
255  if(pos == String::npos)
256  break;
257  pos = shader_src_full.find(' ', pos + 7) + 1;
258  pos2 = shader_src_full.find(';', pos);
259  ins.insert(shader_src_full.substr(pos, pos2 - pos));
260  pos = pos2;
261  }
262  for(pos = 0;;) {
263  pos = shader_src_full.find("static ", pos);
264  if(pos == String::npos)
265  break;
266  pos2 = shader_src_full.find(';', pos);
267  String sub = shader_src_full.substr(pos + 7, pos2 - (pos + 7));
268  if(sub.find("position") != String::npos)
269  sub = " : POSITION";
270  else if(sub.find("color") != String::npos)
271  sub = " : COLOR";
272  else
273  sub.clear();
274  shader_src_full = shader_src_full.substr(0, pos) + shader_src_full.substr(pos + 7, pos2 - (pos + 7))
275  + sub + shader_src_full.substr(pos2);
276  }
277 
278  pos = shader_src_full.find("void gl_main()");
279  pos2 = shader_src_full.find('{', pos) + 1;
280  for(int count = 1; count; ++pos2) {
281  if(shader_src_full[pos2] == '}')
282  --count;
283  else if(shader_src_full[pos2] == '{')
284  ++count;
285  }
286  String shader_front = shader_src_full.substr(0, pos);
287  String shader_back = shader_src_full.substr(pos2 + 1);
288  String main_body = shader_src_full.substr(pos + 14, (pos2 + 1) - (pos + 14));
289 
290  for(std::set<String>::iterator it = ins.begin(), iend = ins.end(); it != iend; ++it) {
291  for(pos = main_body.size();;) {
292  pos = main_body.rfind(*it, pos);
293  if(pos == String::npos)
294  break;
295  main_body = main_body.substr(0, pos) + "p." + main_body.substr(pos);
296  }
297  }
298  for(pos = main_body.size();;) {
299  pos = main_body.rfind("gl_Color[0]", pos);
300  if(pos == String::npos)
301  break;
302  main_body = main_body.substr(0, pos) + "gl_Color" + main_body.substr(pos + 11);
303  }
304 
305  shader_src_full = shader_front + "float4 ps_main(const PS_INPUT p" + uniforms + ") : COLOR {\nfloat4 gl_Color;" + main_body + "return gl_Color;}";
306  }
307 
308  std::cerr << "Shader Source Full:" << std::endl << shader_src_full << std::endl;
309 
311  LPD3DXBUFFER errors;
312 
313  HRESULT result = vdx.D3DXCompileShader()(shader_src_full.c_str(),
314  shader_src_full.size(),
315  0,
316  0,
317  type == VERTEX ? "vs_main" : "ps_main",
318  type == VERTEX ? "vs_3_0" : "ps_3_0",
319  0,
320  &code,
321  &errors,
322  type == VERTEX ? &m_constant_table : 0);
323 
324  if(FAILED(result)) {
325  std::cerr << "Errors:" << std::endl << reinterpret_cast<char *>(errors->GetBufferPointer());
326  errors->Release();
327  throw Shader_Init_Failure();
328  }
329 
330  if(type == VERTEX)
331  vdx.get_d3d_device()->CreateVertexShader((DWORD*)code->GetBufferPointer(), &m_vertex_shader);
332  else
333  vdx.get_d3d_device()->CreatePixelShader((DWORD*)code->GetBufferPointer(), &m_pixel_shader);
334 
335  code->Release();
336  }
337 
339  if(m_constant_table) {
340  m_constant_table->Release();
341  if(m_vertex_shader)
342  m_vertex_shader->Release();
343  }
344  else if(m_pixel_shader)
345  m_pixel_shader->Release();
346  }
347 
349  : m_vertex_shader(0),
350  m_fragment_shader(0)
351  {
352  }
353 
355  }
356 
358  Shader_DX9 &sdx = dynamic_cast<Shader_DX9 &>(shader);
359 
360  if(sdx.type() == Shader::VERTEX) {
361  if(m_vertex_shader)
362  throw Shader_Link_Failure();
363  m_vertex_shader = &sdx;
364  }
365  else {
366  if(m_fragment_shader)
367  throw Shader_Link_Failure();
368  m_fragment_shader = &sdx;
369  }
370  }
371 
373  }
374 #endif
375 
376 }
#define GL_TRUE
Definition: gl2.h:51
void attach(Shader &shader)
Definition: Shader.cpp:56
#define glLinkProgramARB
Definition: glew.h:5677
#define GL_FRAGMENT_SHADER
Definition: gl2.h:259
#define GL_LINK_STATUS
Definition: gl2.h:270
The Direct3D9 Rendering System.
Definition: Video_DX9.h:62
void clear()
Definition: String.cpp:323
LPDIRECT3DDEVICE9 & get_d3d_device()
See DirectX Documentation for details.
Definition: Video_DX9.hxx:48
GLint GLenum GLsizei GLsizei GLsizei GLint GLenum GLenum type
Definition: gl2ext.h:845
#define glCreateShaderObjectARB
Definition: glew.h:5664
GL_APICALL void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar **string, const GLint *length)
size_t find(const String &str, size_t pos=0) const
Definition: String.cpp:480
typedef HRESULT(WINAPI *LPD3DXIMTSIGNALCALLBACK)(CONST D3DXVECTOR2 *uv
virtual ~Program_GL_Shader()
Definition: Shader.cpp:103
virtual ~Shader_GL_Fixed()
Definition: Shader.cpp:39
Shader::Type type() const
Definition: Shader.hxx:49
GLuint get() const
Definition: Shader.hxx:29
#define GL_INFO_LOG_LENGTH
Definition: gl2.h:410
const char * c_str() const
Definition: String.cpp:467
GLenum GLsizei len
Definition: glew.h:7035
#define GL_VERTEX_SHADER
Definition: gl2.h:260
GL_APICALL void GL_APIENTRY glDeleteShader(GLuint shader)
String substr(size_t pos=0, size_t n=npos) const
Definition: String.cpp:510
GL_APICALL void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei *length, GLchar *infolog)
static D3DXCompileShader_fcn D3DXCompileShader()
Definition: Video_DX9.h:118
#define glCompileShaderARB
Definition: glew.h:5662
GL_APICALL GLuint GL_APIENTRY glCreateProgram(void)
GL_APICALL void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
GLuint64EXT * result
Definition: glew.h:12708
GLuint shader
Definition: glew.h:1799
GL_APICALL GLuint GL_APIENTRY glCreateShader(GLenum type)
GL_APICALL void GL_APIENTRY glLinkProgram(GLuint program)
LPDIRECT3DPIXELSHADER9 m_pixel_shader
Definition: Shader.h:220
GLint GLsizei count
Definition: gl2ext.h:1011
GL_APICALL void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint *params)
GLuint get() const
Definition: Shader.hxx:39
size_t rfind(const String &str, size_t pos=npos) const
Definition: String.cpp:485
static const size_type npos
Definition: String.h:37
#define GL_COMPILE_STATUS
Definition: gl2.h:409
GL_APICALL void GL_APIENTRY glCompileShader(GLuint shader)
#define glShaderSourceARB
Definition: glew.h:5678
Definition: inftrees.h:24
GL_APICALL void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *infolog)
int GLint
Definition: gl2.h:28
LPDIRECT3DVERTEXSHADER9 m_vertex_shader
Definition: Shader.h:219
A base class for Vertex_Shader and Fragment_Shader.
Definition: Shader.h:97
GL_APICALL void GL_APIENTRY glDeleteProgram(GLuint program)
typedef DWORD(WINAPI *XInputGetState_t)(DWORD dwUserIndex
void attach(Shader &shader)
Definition: Shader.cpp:111
size_t size() const
Definition: String.cpp:310
interface ID3DXBuffer * LPD3DXBUFFER
Definition: d3dx9core.h:97
void attach(Shader &shader)
Definition: Shader.cpp:357
#define glGetProgramivARB
Definition: glew.h:7084
#define GL_FRAGMENT_SHADER_ARB
Definition: glew.h:4005
virtual ~Program_DX9()
Definition: Shader.cpp:354
GL_APICALL void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint *params)
GL_APICALL void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)
#define GL_VERTEX_SHADER_ARB
Definition: glew.h:7146