Decal.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. /******************************************************************************/
  5. #define OPAQUE_FRAC 0.8f
  6. // Flt alpha=1-Sat((Abs(pos.z)-opaque_frac)/(1-opaque_frac));
  7. // Flt alpha=Sat(Abs(pos.z)/-(1-opaque_frac) + (opaque_frac/(1-opaque_frac)+1));
  8. // Flt alpha=Sat(Abs(pos.z)*(1/(opaque_frac-1)) + (opaque_frac/(1-opaque_frac)+1));
  9. inline Flt OpaqueFracMul(Flt frac=OPAQUE_FRAC) {return 1.0f/(frac-1);}
  10. inline Flt OpaqueFracAdd(Flt frac=OPAQUE_FRAC) {return frac/(1-frac)+1;}
  11. /******************************************************************************/
  12. void Decal::zero()
  13. {
  14. terrain_only=false;
  15. color=1;
  16. matrix.identity();
  17. Zero(_shader);
  18. }
  19. void Decal::del()
  20. {
  21. _material.clear();
  22. zero();
  23. }
  24. Decal::Decal() {zero();}
  25. void Decal::setShader()
  26. {
  27. REPD(f, 2)
  28. REPD(p, 2)
  29. {
  30. if(_material && _material->base_0)
  31. {
  32. _shader[f][p]=Sh.get(S+"Decal"+(f ? 'F' : '\0')+(p ? 'P' : _material->base_1 ? 'N' : '\0'));
  33. }else _shader[f][p]=null;
  34. }
  35. }
  36. Decal& Decal::material(C MaterialPtr &material)
  37. {
  38. if(T._material!=material)
  39. {
  40. T._material=material;
  41. setShader();
  42. }
  43. return T;
  44. }
  45. Decal& Decal::setMatrix(C Matrix &object_world_matrix, C Matrix &decal_world_matrix)
  46. {
  47. object_world_matrix.inverse(matrix);
  48. decal_world_matrix.mul (matrix, matrix); // 'matrix'=local matrix
  49. return T;
  50. }
  51. /******************************************************************************/
  52. void Decal::drawStatic(Flt alpha)C
  53. {
  54. if(_shader[0][0] && Renderer.canReadDepth())
  55. {
  56. BallM ball((matrix.x+matrix.y+matrix.z).length(), matrix.pos);
  57. if(Frustum(ball))
  58. {
  59. Bool inside=Cuts(CamMatrix.pos, ball.extend(Frustum.view_quad_max_dist));
  60. if(Shader *shader=T._shader[inside][Renderer._palette_mode])
  61. {
  62. SetOneMatrix(matrix);
  63. _material->setBlend();
  64. Sh.h_DecalParams->set(Vec(OpaqueFracMul(), OpaqueFracAdd(), alpha));
  65. Sh.h_Color[0] ->set(color);
  66. if(terrain_only)D.stencil(STENCIL_TERRAIN_TEST);
  67. //Bool cwrt; Byte cwrt_old; if(cwrt=(Renderer.cur[1] && tech!=Sh.h_DecalN)){cwrt_old=D._cwrt[1]; D.colWrite(0, 1);} it looks like if the shader doesn't write to RT then it's not applied
  68. Renderer.needDepthRead();
  69. D.alpha(Renderer._palette_mode ? ALPHA_ADD : ALPHA_BLEND_FACTOR);
  70. if(inside)
  71. {
  72. shader->draw(_material->base_0());
  73. }else
  74. {
  75. shader->begin(); D.cull(true); D.depth(true); D.depthWrite(false); MshrBox.set().drawFull(); ShaderEnd();
  76. }
  77. //if(cwrt)D.colWrite(cwrt_old, 1);
  78. if(terrain_only)D.stencil(STENCIL_NONE);
  79. }
  80. }
  81. }
  82. }
  83. void Decal::drawAnimated(C Matrix &object_world_matrix, Flt alpha)C
  84. {
  85. if(_shader[0][0] && Renderer.canReadDepth())
  86. {
  87. Matrix m; matrix.mul(object_world_matrix, m);
  88. BallM ball((m.x+m.y+m.z).length(), m.pos);
  89. if(Frustum(ball))
  90. {
  91. Bool inside=Cuts(CamMatrix.pos, ball.extend(Frustum.view_quad_max_dist));
  92. if(Shader *shader=T._shader[inside][Renderer._palette_mode])
  93. {
  94. SetOneMatrix(m);
  95. _material->setBlend();
  96. Sh.h_DecalParams->set(Vec(OpaqueFracMul(), OpaqueFracAdd(), alpha));
  97. Sh.h_Color[0] ->set(color);
  98. if(terrain_only)D.stencil(STENCIL_TERRAIN_TEST);
  99. //Bool cwrt; Byte cwrt_old; if(cwrt=(Renderer.cur[1] && tech!=Sh.h_DecalN)){cwrt_old=D._cwrt[1]; D.colWrite(0, 1);} it looks like if the shader doesn't write to RT then it's not applied
  100. Renderer.needDepthRead();
  101. D.alpha(Renderer._palette_mode ? ALPHA_ADD : ALPHA_BLEND_FACTOR);
  102. if(inside)
  103. {
  104. shader->draw(_material->base_0());
  105. }else
  106. {
  107. shader->begin(); D.cull(true); D.depth(true); D.depthWrite(false); MshrBox.set().drawFull(); ShaderEnd();
  108. }
  109. //if(cwrt)D.colWrite(cwrt_old, 1);
  110. if(terrain_only)D.stencil(STENCIL_NONE);
  111. }
  112. }
  113. }
  114. }
  115. /******************************************************************************/
  116. Bool Decal::save(File &f)C
  117. {
  118. f.cmpUIntV(0); // version
  119. f<<terrain_only<<color<<matrix;
  120. f.putAsset(_material.id());
  121. return f.ok();
  122. }
  123. Bool Decal::load(File &f)
  124. {
  125. switch(f.decUIntV()) // version
  126. {
  127. case 0:
  128. {
  129. f>>terrain_only>>color>>matrix;
  130. _material=f.getAssetID();
  131. setShader();
  132. if(f.ok())return true;
  133. }break;
  134. }
  135. del(); return false;
  136. }
  137. /******************************************************************************/
  138. }
  139. /******************************************************************************/