Render3D.cpp 13 KB

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