/src/dep/src/irrlicht/COpenGLShaderMaterialRenderer.cpp

https://github.com/Pepsi1x1/pseuwow · C++ · 258 lines · 173 code · 65 blank · 20 comment · 34 complexity · 303531f4541d97b3df2794f738c3e283 MD5 · raw file

  1. // Copyright (C) 2002-2008 Nikolaus Gebhardt
  2. // This file is part of the "Irrlicht Engine".
  3. // For conditions of distribution and use, see copyright notice in irrlicht.h
  4. #include "IrrCompileConfig.h"
  5. #ifdef _IRR_COMPILE_WITH_OPENGL_
  6. #include "COpenGLShaderMaterialRenderer.h"
  7. #include "IGPUProgrammingServices.h"
  8. #include "IShaderConstantSetCallBack.h"
  9. #include "IVideoDriver.h"
  10. #include "os.h"
  11. #include "COpenGLDriver.h"
  12. namespace irr
  13. {
  14. namespace video
  15. {
  16. //! Constructor
  17. COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(video::COpenGLDriver* driver,
  18. s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
  19. IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
  20. : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
  21. VertexShader(0), PixelShader(0), UserData(userData)
  22. {
  23. #ifdef _DEBUG
  24. setDebugName("COpenGLShaderMaterialRenderer");
  25. #endif
  26. if (BaseMaterial)
  27. BaseMaterial->grab();
  28. if (CallBack)
  29. CallBack->grab();
  30. init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram, EVT_STANDARD);
  31. }
  32. //! constructor only for use by derived classes who want to
  33. //! create a fall back material for example.
  34. COpenGLShaderMaterialRenderer::COpenGLShaderMaterialRenderer(COpenGLDriver* driver,
  35. IShaderConstantSetCallBack* callback,
  36. IMaterialRenderer* baseMaterial, s32 userData)
  37. : Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
  38. VertexShader(0), PixelShader(0), UserData(userData)
  39. {
  40. if (BaseMaterial)
  41. BaseMaterial->grab();
  42. if (CallBack)
  43. CallBack->grab();
  44. }
  45. //! Destructor
  46. COpenGLShaderMaterialRenderer::~COpenGLShaderMaterialRenderer()
  47. {
  48. if (CallBack)
  49. CallBack->drop();
  50. if (VertexShader)
  51. Driver->extGlDeletePrograms(1, &VertexShader);
  52. if (PixelShader)
  53. Driver->extGlDeletePrograms(1, &PixelShader);
  54. if (BaseMaterial)
  55. BaseMaterial->drop();
  56. }
  57. void COpenGLShaderMaterialRenderer::init(s32& outMaterialTypeNr, const c8* vertexShaderProgram,
  58. const c8* pixelShaderProgram, E_VERTEX_TYPE type)
  59. {
  60. outMaterialTypeNr = -1;
  61. bool success;
  62. // create vertex shader
  63. success=createVertexShader(vertexShaderProgram);
  64. // create pixel shader
  65. if (!createPixelShader(pixelShaderProgram) || !success)
  66. return;
  67. // register as a new material
  68. outMaterialTypeNr = Driver->addMaterialRenderer(this);
  69. }
  70. bool COpenGLShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
  71. {
  72. // call callback to set shader constants
  73. if (CallBack && (VertexShader || PixelShader))
  74. CallBack->OnSetConstants(service, UserData);
  75. return true;
  76. }
  77. void COpenGLShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
  78. bool resetAllRenderstates, video::IMaterialRendererServices* services)
  79. {
  80. if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
  81. {
  82. #ifdef GL_ARB_vertex_program
  83. if (VertexShader)
  84. {
  85. // set new vertex shader
  86. Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader);
  87. glEnable(GL_VERTEX_PROGRAM_ARB);
  88. }
  89. #endif
  90. // set new pixel shader
  91. #ifdef GL_ARB_fragment_program
  92. if (PixelShader)
  93. {
  94. Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader);
  95. glEnable(GL_FRAGMENT_PROGRAM_ARB);
  96. }
  97. #endif
  98. if (BaseMaterial)
  99. BaseMaterial->OnSetMaterial(material, material, true, services);
  100. }
  101. //let callback know used material
  102. if (CallBack)
  103. CallBack->OnSetMaterial(material);
  104. for (u32 i=0; i<MATERIAL_MAX_TEXTURES; ++i)
  105. Driver->setTexture(i, material.getTexture(i));
  106. Driver->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
  107. }
  108. void COpenGLShaderMaterialRenderer::OnUnsetMaterial()
  109. {
  110. // disable vertex shader
  111. #ifdef GL_ARB_vertex_program
  112. if (VertexShader)
  113. glDisable(GL_VERTEX_PROGRAM_ARB);
  114. #endif
  115. #ifdef GL_ARB_fragment_program
  116. if (PixelShader)
  117. glDisable(GL_FRAGMENT_PROGRAM_ARB);
  118. #endif
  119. if (BaseMaterial)
  120. BaseMaterial->OnUnsetMaterial();
  121. }
  122. //! Returns if the material is transparent.
  123. bool COpenGLShaderMaterialRenderer::isTransparent() const
  124. {
  125. return BaseMaterial ? BaseMaterial->isTransparent() : false;
  126. }
  127. bool COpenGLShaderMaterialRenderer::createPixelShader(const c8* pxsh)
  128. {
  129. if (!pxsh)
  130. return true;
  131. Driver->extGlGenPrograms(1, &PixelShader);
  132. #ifdef GL_ARB_fragment_program
  133. Driver->extGlBindProgram(GL_FRAGMENT_PROGRAM_ARB, PixelShader);
  134. // clear error buffer
  135. while(glGetError() != GL_NO_ERROR)
  136. {}
  137. // compile
  138. Driver->extGlProgramString(GL_FRAGMENT_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
  139. strlen(pxsh), pxsh);
  140. #endif
  141. #ifdef GL_ARB_vertex_program
  142. GLenum g = glGetError();
  143. if (g != GL_NO_ERROR)
  144. {
  145. GLint errPos;
  146. glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
  147. const char* errString = reinterpret_cast<const char*>(glGetString(GL_PROGRAM_ERROR_STRING_ARB));
  148. char tmp[2048];
  149. sprintf(tmp, "Pixel shader compilation failed at position %d:\n%s", errPos, errString);
  150. os::Printer::log(tmp);
  151. Driver->extGlDeletePrograms(1, &PixelShader);
  152. PixelShader=0;
  153. return false;
  154. }
  155. #else
  156. return false;
  157. #endif
  158. return true;
  159. }
  160. bool COpenGLShaderMaterialRenderer::createVertexShader(const c8* vtxsh)
  161. {
  162. if (!vtxsh)
  163. return true;
  164. #ifdef GL_ARB_vertex_program
  165. Driver->extGlGenPrograms(1, &VertexShader);
  166. Driver->extGlBindProgram(GL_VERTEX_PROGRAM_ARB, VertexShader);
  167. // clear error buffer
  168. while(glGetError() != GL_NO_ERROR)
  169. {}
  170. // compile
  171. Driver->extGlProgramString(GL_VERTEX_PROGRAM_ARB, GL_PROGRAM_FORMAT_ASCII_ARB,
  172. strlen(vtxsh), vtxsh);
  173. GLenum g = glGetError();
  174. if (g != GL_NO_ERROR)
  175. {
  176. GLint errPos;
  177. glGetIntegerv( GL_PROGRAM_ERROR_POSITION_ARB, &errPos );
  178. const char* errString = reinterpret_cast<const char*>(glGetString(GL_PROGRAM_ERROR_STRING_ARB));
  179. char tmp[2048];
  180. sprintf(tmp, "Vertex shader compilation failed at position %d:\n%s", errPos, errString);
  181. os::Printer::log(tmp);
  182. Driver->extGlDeletePrograms(1, &VertexShader);
  183. VertexShader=0;
  184. return false;
  185. }
  186. #else
  187. return false;
  188. #endif
  189. return true;
  190. }
  191. } // end namespace video
  192. } // end namespace irr
  193. #endif