Render3D.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  1. #include "Render3D.h"
  2. #include "Shader.h"
  3. #include "Model3D.h"
  4. #include "DXBuffer.h"
  5. #include "Textur.h"
  6. #include "Bild.h"
  7. #include <d3d11.h>
  8. using namespace Framework;
  9. // Inhalt der Render3D Klasse
  10. // Konstruktor
  11. Render3D::Render3D()
  12. {
  13. device = 0;
  14. context = 0;
  15. texturRS = 0;
  16. meshRS = 0;
  17. defaultTextur = new Textur();
  18. Bild *b = new Bild();
  19. b->neuBild( 10, 10, 0xFFFFFFFF );
  20. defaultTextur->setBildZ( b );
  21. shader = new RCArray< RCArray< Shader > >();
  22. shaderId = new Array< int >();
  23. lastObjektId = -1;
  24. lastTexturId = -1;
  25. ref = 1;
  26. }
  27. // Destruktor
  28. Render3D::~Render3D()
  29. {
  30. if( device )
  31. device->Release();
  32. if( context )
  33. context->Release();
  34. if( texturRS )
  35. texturRS->Release();
  36. if( meshRS )
  37. meshRS->Release();
  38. defaultTextur->release();
  39. shader->release();
  40. shaderId->release();
  41. }
  42. // Setzt das Device, was zum zeichnen verwendet werden soll
  43. // device: Das neue Device
  44. void Render3D::setDevice( ID3D11Device *device )
  45. {
  46. if( this->device )
  47. this->device->Release();
  48. this->device = device;
  49. if( device )
  50. {
  51. if( !texturRS )
  52. {
  53. D3D11_RASTERIZER_DESC rasterDesc;
  54. ZeroMemory( &rasterDesc, sizeof( rasterDesc ) );
  55. rasterDesc.AntialiasedLineEnable = false;
  56. rasterDesc.CullMode = D3D11_CULL_BACK;
  57. rasterDesc.DepthBiasClamp = 0.0f;
  58. rasterDesc.DepthClipEnable = true;
  59. rasterDesc.FillMode = D3D11_FILL_SOLID;
  60. rasterDesc.FrontCounterClockwise = false;
  61. rasterDesc.MultisampleEnable = false;
  62. rasterDesc.ScissorEnable = false;
  63. rasterDesc.SlopeScaledDepthBias = 0.0f;
  64. device->CreateRasterizerState( &rasterDesc, &texturRS );
  65. }
  66. if( !meshRS )
  67. {
  68. D3D11_RASTERIZER_DESC rasterDesc;
  69. ZeroMemory( &rasterDesc, sizeof( rasterDesc ) );
  70. rasterDesc.AntialiasedLineEnable = false;
  71. rasterDesc.CullMode = D3D11_CULL_BACK;
  72. rasterDesc.DepthBiasClamp = 0.0f;
  73. rasterDesc.DepthClipEnable = true;
  74. rasterDesc.FillMode = D3D11_FILL_WIREFRAME;
  75. rasterDesc.FrontCounterClockwise = false;
  76. rasterDesc.MultisampleEnable = false;
  77. rasterDesc.ScissorEnable = false;
  78. rasterDesc.SlopeScaledDepthBias = 0.0f;
  79. device->CreateRasterizerState( &rasterDesc, &meshRS );
  80. }
  81. if( context )
  82. {
  83. context->RSSetState( texturRS );
  84. defaultTextur->updateTextur( this );
  85. }
  86. }
  87. }
  88. // Setzt das Context Objekt, das zum Zeichnen verwendet werden soll
  89. // context: das neue Conext Objekt
  90. void Render3D::setContext( ID3D11DeviceContext *context )
  91. {
  92. if( this->context )
  93. this->context->Release();
  94. this->context = context;
  95. if( context )
  96. {
  97. if( texturRS )
  98. context->RSSetState( texturRS );
  99. if( device )
  100. defaultTextur->updateTextur( this );
  101. }
  102. }
  103. // Setzt den aktuellen Shader. Er wird hinten an die Liste mit zuletzt verwendeten Shadern angefügt
  104. // listIndex: Der Index der Liste mit zuletzt verwendeten Shadern
  105. // sh: Der Shader, der verwendet werden soll
  106. void Render3D::benutzeShader( int listIndex, Shader *sh )
  107. {
  108. if( listIndex < 0 )
  109. return;
  110. if( !shader->z( listIndex ) || !shaderId->hat( listIndex ) )
  111. {
  112. shader->set( new RCArray< Shader >(), listIndex );
  113. shaderId->set( -1, listIndex );
  114. }
  115. int id = shaderId->get( listIndex ) + 1;
  116. shader->z( listIndex )->set( sh, id );
  117. shaderId->set( id, listIndex );
  118. sh->benutzeShader( context );
  119. }
  120. // Sprinkt in der Liste mit zuletzt benutzten Shadern zurück und benutzt wieder den dortiegen Shader
  121. // listIndex: Der Index der Liste mit zuletzt verwe deten Shadern
  122. // anz: Die Anzahl der Shader, die zurückgesprungen werden soll. Bei 0 passiert nichts
  123. void Render3D::releaseShader( int listIndex, int anz )
  124. {
  125. if( !shader->z( listIndex ) || !shaderId->hat( listIndex ) || anz < 0 )
  126. return;
  127. int id = shaderId->get( listIndex ) - anz;
  128. if( id < 0 )
  129. id = 0;
  130. if( shader->z( listIndex )->z( id ) )
  131. shader->z( listIndex )->z( id )->benutzeShader( context );
  132. shaderId->set( id, listIndex );
  133. }
  134. // Setzt die View und Projektion Matrizen, die zum zeichnen verwendet werden sollen
  135. // view: Die View Matrix der Kamera
  136. // proj: Die Projektion Matrix der Kamera
  137. // kamPos: Die Position der Kamera in der Welt
  138. void Render3D::setKameraMatrix( Mat4< float > &view, Mat4< float > &proj, Vec3< float > &kamPos )
  139. {
  140. this->view = view;
  141. this->proj = proj;
  142. this->kamPos = kamPos;
  143. Mat4< float > tmp = proj * view;
  144. frustrum[ 0 ].x = tmp.elements[ 3 ][ 0 ] + tmp.elements[ 0 ][ 0 ];
  145. frustrum[ 0 ].y = tmp.elements[ 3 ][ 1 ] + tmp.elements[ 0 ][ 1 ];
  146. frustrum[ 0 ].z = tmp.elements[ 3 ][ 2 ] + tmp.elements[ 0 ][ 2 ];
  147. frustrum[ 0 ].w = tmp.elements[ 3 ][ 3 ] + tmp.elements[ 0 ][ 3 ];
  148. frustrum[ 1 ].x = tmp.elements[ 3 ][ 0 ] - tmp.elements[ 0 ][ 0 ];
  149. frustrum[ 1 ].y = tmp.elements[ 3 ][ 1 ] - tmp.elements[ 0 ][ 1 ];
  150. frustrum[ 1 ].z = tmp.elements[ 3 ][ 2 ] - tmp.elements[ 0 ][ 2 ];
  151. frustrum[ 1 ].w = tmp.elements[ 3 ][ 3 ] - tmp.elements[ 0 ][ 3 ];
  152. frustrum[ 2 ].x = tmp.elements[ 3 ][ 0 ] - tmp.elements[ 1 ][ 0 ];
  153. frustrum[ 2 ].y = tmp.elements[ 3 ][ 1 ] - tmp.elements[ 1 ][ 1 ];
  154. frustrum[ 2 ].z = tmp.elements[ 3 ][ 2 ] - tmp.elements[ 1 ][ 2 ];
  155. frustrum[ 2 ].w = tmp.elements[ 3 ][ 3 ] - tmp.elements[ 1 ][ 3 ];
  156. frustrum[ 3 ].x = tmp.elements[ 3 ][ 0 ] + tmp.elements[ 1 ][ 0 ];
  157. frustrum[ 3 ].y = tmp.elements[ 3 ][ 1 ] + tmp.elements[ 1 ][ 1 ];
  158. frustrum[ 3 ].z = tmp.elements[ 3 ][ 2 ] + tmp.elements[ 1 ][ 2 ];
  159. frustrum[ 3 ].w = tmp.elements[ 3 ][ 3 ] + tmp.elements[ 1 ][ 3 ];
  160. frustrum[ 4 ].x = tmp.elements[ 2 ][ 0 ];
  161. frustrum[ 4 ].y = tmp.elements[ 2 ][ 1 ];
  162. frustrum[ 4 ].z = tmp.elements[ 2 ][ 2 ];
  163. frustrum[ 4 ].w = tmp.elements[ 2 ][ 3 ];
  164. frustrum[ 5 ].x = tmp.elements[ 3 ][ 0 ] - tmp.elements[ 2 ][ 0 ];
  165. frustrum[ 5 ].y = tmp.elements[ 3 ][ 1 ] - tmp.elements[ 2 ][ 1 ];
  166. frustrum[ 5 ].z = tmp.elements[ 3 ][ 2 ] - tmp.elements[ 2 ][ 2 ];
  167. frustrum[ 5 ].w = tmp.elements[ 3 ][ 3 ] - tmp.elements[ 2 ][ 3 ];
  168. for( int i = 0; i < 6; i++ )
  169. frustrum[ i ].normalize();
  170. }
  171. // Beginnt das Zeichnen eines bestimmten objektes
  172. // zMdl: Das 3D Modelohne erhöhten Reference Counter
  173. void Render3D::beginnModel( Model3D *zMdl )
  174. {
  175. Mat4< float > trans = proj * view;
  176. int anz = zMdl->errechneMatrizen( trans, matrixBuffer );
  177. if( shader->z( VERTEX ) && shaderId->hat( VERTEX ) )
  178. shader->z( VERTEX )->z( shaderId->get( VERTEX ) )->füllConstBuffer( context, (char*)matrixBuffer, 0, sizeof( Mat4< float > ) * anz );
  179. if( lastObjektId == -1 || lastObjektId != zMdl->getDatenId() )
  180. {
  181. lastObjektId = zMdl->getDatenId();
  182. unsigned int offset = 0;
  183. ID3D11Buffer *b = zMdl->zVertexBuffer()->zBuffer();
  184. unsigned int es = (unsigned)zMdl->zVertexBuffer()->getElementLength();
  185. context->IASetVertexBuffers( 0, 1, &b, &es, &offset );
  186. }
  187. }
  188. // Zeichnet eine bestimmte struktur
  189. // zIndexBuffer: Ein IndexBuffer, der auf verschiedene Vertices aus dem Vertex Buffer des Models zeigt. Ohne erhöhten Reference Counter
  190. // textur: Ein Zeiger auf die Textur, die verwendet werden soll ohne erhöhten Reference Counter
  191. // struktur: Die Struktur der angegebenen Indices, Beispiel: D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST oder D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP ...
  192. void Render3D::draw( DXIndexBuffer *zIndexBuffer, Textur *textur, D3D_PRIMITIVE_TOPOLOGY struktur )
  193. {
  194. DXGI_FORMAT f = DXGI_FORMAT_R32_UINT;
  195. if( zIndexBuffer->getElementLength() == 2 )
  196. f = DXGI_FORMAT_R16_UINT;
  197. if( zIndexBuffer->getElementLength() == 1 )
  198. f = DXGI_FORMAT_R8_UINT;
  199. context->IASetIndexBuffer( zIndexBuffer->zBuffer(), f, 0 );
  200. context->IASetPrimitiveTopology( struktur );
  201. if( textur )
  202. {
  203. if( lastTexturId == -1 || lastTexturId != textur->getId() )
  204. {
  205. lastTexturId = textur->getId();
  206. ID3D11ShaderResourceView *v = *textur;
  207. context->PSSetShaderResources( 0, 1, &v );
  208. }
  209. context->DrawIndexed( zIndexBuffer->getElementAnzahl(), 0, 0 );
  210. }
  211. else
  212. {
  213. context->RSSetState( meshRS );
  214. ID3D11ShaderResourceView *v = *defaultTextur;
  215. context->PSSetShaderResources( 0, 1, &v );
  216. context->DrawIndexed( zIndexBuffer->getElementAnzahl(), 0, 0 );
  217. context->RSSetState( texturRS );
  218. }
  219. }
  220. // Gibt einen der aktuell verwendeten Shader zurück
  221. // listIndex: Der Index der Lise mit Shadern, von denen der aktuell benutzte zurückgegeben werden soll
  222. Shader *Render3D::getShader( int listIndex ) const
  223. {
  224. if( !shader->z( listIndex ) || !shaderId->hat( listIndex ) )
  225. return 0;
  226. return shader->z( listIndex )->get( shaderId->get( listIndex ) );
  227. }
  228. // Gibt einen der aktuell verwendeten Shader ohne erhöhten Reference Counter zurück
  229. // listIndex: Der Index der Lise mit Shadern, von denen der aktuell benutzte zurückgegeben werden soll
  230. Shader *Render3D::zShader( int listIndex ) const
  231. {
  232. if( !shader->z( listIndex ) || !shaderId->hat( listIndex ) )
  233. return 0;
  234. return shader->z( listIndex )->z( shaderId->get( listIndex ) );
  235. }
  236. // Gibt das momentan verwendete Device Objekt ohne erhöhten Reference Counter zurück
  237. ID3D11Device *Render3D::zDevice() const
  238. {
  239. return device;
  240. }
  241. // Gibt das momentan verwendete Context Objekt ohne erhöhten Reference Counter zurück
  242. ID3D11DeviceContext *Render3D::zContext() const
  243. {
  244. return context;
  245. }
  246. // Überprüft, ob eine Kugel in dem Sichtbaren Raum der Welt liegt und gezeichnet werden muss
  247. // pos: Der Mittelpunkt der Kugel
  248. // radius: Der Radius der Kugel
  249. // dist: Einen Zeiger auf einen float, in dem das quadrat des Abstands zur Kammeraposition gespeichert wird, falls diese Funktion true zurückgiebt und der Zeiger nicht 0 ist
  250. bool Render3D::isInFrustrum( const Vec3< float > &pos, float radius, float *dist ) const
  251. {
  252. for( int i = 0; i < 6; i++ )
  253. {
  254. if( frustrum[ i ] * pos + radius < 0 )
  255. return 0;
  256. }
  257. if( dist )
  258. *dist = kamPos.abstandSq( pos );
  259. return 1;
  260. }
  261. // Erhöht den Reference Counting Zähler.
  262. // return: this.
  263. Render3D *Render3D::getThis()
  264. {
  265. ref++;
  266. return this;
  267. }
  268. // Verringert den Reference Counting Zähler. Wenn der Zähler 0 erreicht, wird das Zeichnung automatisch gelöscht.
  269. // return: 0.
  270. Render3D *Render3D::release()
  271. {
  272. ref--;
  273. if( !ref )
  274. delete this;
  275. return 0;
  276. }