tinyGraphicsStateGuardian.cxx 114 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266
  1. // Filename: tinyGraphicsStateGuardian.cxx
  2. // Created by: drose (24Apr08)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. //
  6. // PANDA 3D SOFTWARE
  7. // Copyright (c) Carnegie Mellon University. All rights reserved.
  8. //
  9. // All use of this software is subject to the terms of the revised BSD
  10. // license. You should have received a copy of this license along
  11. // with this source code in a file named "LICENSE."
  12. //
  13. ////////////////////////////////////////////////////////////////////
  14. #include "tinyGraphicsStateGuardian.h"
  15. #include "tinyGeomMunger.h"
  16. #include "tinyTextureContext.h"
  17. #include "config_tinydisplay.h"
  18. #include "pStatTimer.h"
  19. #include "geomVertexReader.h"
  20. #include "ambientLight.h"
  21. #include "pointLight.h"
  22. #include "directionalLight.h"
  23. #include "spotlight.h"
  24. #include "depthWriteAttrib.h"
  25. #include "depthOffsetAttrib.h"
  26. #include "colorWriteAttrib.h"
  27. #include "alphaTestAttrib.h"
  28. #include "depthTestAttrib.h"
  29. #include "shadeModelAttrib.h"
  30. #include "cullFaceAttrib.h"
  31. #include "rescaleNormalAttrib.h"
  32. #include "materialAttrib.h"
  33. #include "lightAttrib.h"
  34. #include "scissorAttrib.h"
  35. #include "bitMask.h"
  36. #include "zgl.h"
  37. #include "zmath.h"
  38. #include "ztriangle_table.h"
  39. #include "store_pixel_table.h"
  40. #include "graphicsEngine.h"
  41. TypeHandle TinyGraphicsStateGuardian::_type_handle;
  42. PStatCollector TinyGraphicsStateGuardian::_vertices_immediate_pcollector("Vertices:Immediate mode");
  43. PStatCollector TinyGraphicsStateGuardian::_draw_transform_pcollector("Draw:Transform");
  44. PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_untextured_pcollector("Pixels:White untextured");
  45. PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_untextured_pcollector("Pixels:Flat untextured");
  46. PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_untextured_pcollector("Pixels:Smooth untextured");
  47. PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_textured_pcollector("Pixels:White textured");
  48. PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_textured_pcollector("Pixels:Flat textured");
  49. PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_textured_pcollector("Pixels:Smooth textured");
  50. PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_perspective_pcollector("Pixels:White perspective");
  51. PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_perspective_pcollector("Pixels:Flat perspective");
  52. PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_perspective_pcollector("Pixels:Smooth perspective");
  53. PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_multitex2_pcollector("Pixels:Smooth multitex 2");
  54. PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_multitex3_pcollector("Pixels:Smooth multitex 3");
  55. ////////////////////////////////////////////////////////////////////
  56. // Function: TinyGraphicsStateGuardian::Constructor
  57. // Access: Public
  58. // Description:
  59. ////////////////////////////////////////////////////////////////////
  60. TinyGraphicsStateGuardian::
  61. TinyGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
  62. TinyGraphicsStateGuardian *share_with) :
  63. GraphicsStateGuardian(CS_yup_right, engine, pipe)
  64. {
  65. _current_frame_buffer = NULL;
  66. _aux_frame_buffer = NULL;
  67. _c = NULL;
  68. _vertices = NULL;
  69. _vertices_size = 0;
  70. }
  71. ////////////////////////////////////////////////////////////////////
  72. // Function: TinyGraphicsStateGuardian::Destructor
  73. // Access: Public
  74. // Description:
  75. ////////////////////////////////////////////////////////////////////
  76. TinyGraphicsStateGuardian::
  77. ~TinyGraphicsStateGuardian() {
  78. }
  79. ////////////////////////////////////////////////////////////////////
  80. // Function: TinyGraphicsStateGuardian::reset
  81. // Access: Public, Virtual
  82. // Description: Resets all internal state as if the gsg were newly
  83. // created.
  84. ////////////////////////////////////////////////////////////////////
  85. void TinyGraphicsStateGuardian::
  86. reset() {
  87. free_pointers();
  88. GraphicsStateGuardian::reset();
  89. // Build _inv_state_mask as a mask of 1's where we don't care, and
  90. // 0's where we do care, about the state.
  91. _inv_state_mask.clear_bit(ColorAttrib::get_class_slot());
  92. _inv_state_mask.clear_bit(ColorScaleAttrib::get_class_slot());
  93. _inv_state_mask.clear_bit(CullFaceAttrib::get_class_slot());
  94. _inv_state_mask.clear_bit(DepthOffsetAttrib::get_class_slot());
  95. _inv_state_mask.clear_bit(RenderModeAttrib::get_class_slot());
  96. _inv_state_mask.clear_bit(RescaleNormalAttrib::get_class_slot());
  97. _inv_state_mask.clear_bit(TextureAttrib::get_class_slot());
  98. _inv_state_mask.clear_bit(MaterialAttrib::get_class_slot());
  99. _inv_state_mask.clear_bit(LightAttrib::get_class_slot());
  100. _inv_state_mask.clear_bit(ScissorAttrib::get_class_slot());
  101. if (_c != (GLContext *)NULL) {
  102. glClose(_c);
  103. _c = NULL;
  104. }
  105. _c = (GLContext *)gl_zalloc(sizeof(GLContext));
  106. glInit(_c, _current_frame_buffer);
  107. _c->draw_triangle_front = gl_draw_triangle_fill;
  108. _c->draw_triangle_back = gl_draw_triangle_fill;
  109. _supported_geom_rendering =
  110. Geom::GR_point |
  111. Geom::GR_indexed_other |
  112. Geom::GR_triangle_strip |
  113. Geom::GR_flat_last_vertex;
  114. _max_texture_dimension = (1 << ZB_POINT_ST_FRAC_BITS);
  115. _max_texture_stages = MAX_TEXTURE_STAGES;
  116. _max_lights = MAX_LIGHTS;
  117. _color_scale_via_lighting = false;
  118. _alpha_scale_via_texture = false;
  119. _runtime_color_scale = true;
  120. _color_material_flags = 0;
  121. _texturing_state = 0;
  122. _texfilter_state = 0;
  123. _texture_replace = false;
  124. _filled_flat = false;
  125. _auto_rescale_normal = false;
  126. // Now that the GSG has been initialized, make it available for
  127. // optimizations.
  128. add_gsg(this);
  129. }
  130. ////////////////////////////////////////////////////////////////////
  131. // Function: TinyGraphicsStateGuardian::free_pointers
  132. // Access: Protected, Virtual
  133. // Description: Frees some memory that was explicitly allocated
  134. // within the glgsg.
  135. ////////////////////////////////////////////////////////////////////
  136. void TinyGraphicsStateGuardian::
  137. free_pointers() {
  138. if (_aux_frame_buffer != (ZBuffer *)NULL) {
  139. ZB_close(_aux_frame_buffer);
  140. _aux_frame_buffer = NULL;
  141. }
  142. if (_vertices != (GLVertex *)NULL) {
  143. PANDA_FREE_ARRAY(_vertices);
  144. _vertices = NULL;
  145. }
  146. _vertices_size = 0;
  147. }
  148. ////////////////////////////////////////////////////////////////////
  149. // Function: TinyGraphicsStateGuardian::close_gsg
  150. // Access: Protected, Virtual
  151. // Description: This is called by the associated GraphicsWindow when
  152. // close_window() is called. It should null out the
  153. // _win pointer and possibly free any open resources
  154. // associated with the GSG.
  155. ////////////////////////////////////////////////////////////////////
  156. void TinyGraphicsStateGuardian::
  157. close_gsg() {
  158. GraphicsStateGuardian::close_gsg();
  159. if (_c != (GLContext *)NULL) {
  160. glClose(_c);
  161. _c = NULL;
  162. }
  163. }
  164. ////////////////////////////////////////////////////////////////////
  165. // Function: TinyGraphicsStateGuardian::depth_offset_decals
  166. // Access: Public, Virtual
  167. // Description: Returns true if this GSG can implement decals using a
  168. // DepthOffsetAttrib, or false if that is unreliable
  169. // and the three-step rendering process should be used
  170. // instead.
  171. ////////////////////////////////////////////////////////////////////
  172. bool TinyGraphicsStateGuardian::
  173. depth_offset_decals() {
  174. return false;
  175. }
  176. ////////////////////////////////////////////////////////////////////
  177. // Function: TinyGraphicsStateGuardian::make_geom_munger
  178. // Access: Public, Virtual
  179. // Description: Creates a new GeomMunger object to munge vertices
  180. // appropriate to this GSG for the indicated state.
  181. ////////////////////////////////////////////////////////////////////
  182. PT(GeomMunger) TinyGraphicsStateGuardian::
  183. make_geom_munger(const RenderState *state, Thread *current_thread) {
  184. PT(TinyGeomMunger) munger = new TinyGeomMunger(this, state);
  185. return GeomMunger::register_munger(munger, current_thread);
  186. }
  187. ////////////////////////////////////////////////////////////////////
  188. // Function: TinyGraphicsStateGuardian::clear
  189. // Access: Public
  190. // Description: Clears the framebuffer within the current
  191. // DisplayRegion, according to the flags indicated by
  192. // the given DrawableRegion object.
  193. //
  194. // This does not set the DisplayRegion first. You
  195. // should call prepare_display_region() to specify the
  196. // region you wish the clear operation to apply to.
  197. ////////////////////////////////////////////////////////////////////
  198. void TinyGraphicsStateGuardian::
  199. clear(DrawableRegion *clearable) {
  200. PStatTimer timer(_clear_pcollector);
  201. if ((!clearable->get_clear_color_active())&&
  202. (!clearable->get_clear_depth_active())&&
  203. (!clearable->get_clear_stencil_active())) {
  204. return;
  205. }
  206. set_state_and_transform(RenderState::make_empty(), _internal_transform);
  207. bool clear_color = false;
  208. int r, g, b, a;
  209. if (clearable->get_clear_color_active()) {
  210. LColor v = clearable->get_clear_color();
  211. r = (int)(v[0] * 0xffff);
  212. g = (int)(v[1] * 0xffff);
  213. b = (int)(v[2] * 0xffff);
  214. a = (int)(v[3] * 0xffff);
  215. clear_color = true;
  216. }
  217. bool clear_z = false;
  218. int z;
  219. if (clearable->get_clear_depth_active()) {
  220. // We ignore the specified depth clear value, since we don't
  221. // support alternate depth compare functions anyway.
  222. z = 0;
  223. clear_z = true;
  224. }
  225. ZB_clear_viewport(_c->zb, clear_z, z,
  226. clear_color, r, g, b, a,
  227. _c->viewport.xmin, _c->viewport.ymin,
  228. _c->viewport.xsize, _c->viewport.ysize);
  229. }
  230. ////////////////////////////////////////////////////////////////////
  231. // Function: TinyGraphicsStateGuardian::prepare_display_region
  232. // Access: Public, Virtual
  233. // Description: Prepare a display region for rendering (set up
  234. // scissor region and viewport)
  235. ////////////////////////////////////////////////////////////////////
  236. void TinyGraphicsStateGuardian::
  237. prepare_display_region(DisplayRegionPipelineReader *dr) {
  238. nassertv(dr != (DisplayRegionPipelineReader *)NULL);
  239. GraphicsStateGuardian::prepare_display_region(dr);
  240. int xmin, ymin, xsize, ysize;
  241. dr->get_region_pixels_i(xmin, ymin, xsize, ysize);
  242. PN_stdfloat pixel_factor = _current_display_region->get_pixel_factor();
  243. if (pixel_factor != 1.0) {
  244. // Render into an aux buffer, and zoom it up into the main
  245. // frame buffer later.
  246. xmin = 0;
  247. ymin = 0;
  248. xsize = int(xsize * pixel_factor);
  249. ysize = int(ysize * pixel_factor);
  250. if (_aux_frame_buffer == (ZBuffer *)NULL) {
  251. _aux_frame_buffer = ZB_open(xsize, ysize, ZB_MODE_RGBA, 0, 0, 0, 0);
  252. } else if (_aux_frame_buffer->xsize < xsize || _aux_frame_buffer->ysize < ysize) {
  253. ZB_resize(_aux_frame_buffer, NULL,
  254. max(_aux_frame_buffer->xsize, xsize),
  255. max(_aux_frame_buffer->ysize, ysize));
  256. }
  257. _c->zb = _aux_frame_buffer;
  258. } else {
  259. // Render directly into the main frame buffer.
  260. _c->zb = _current_frame_buffer;
  261. }
  262. _c->viewport.xmin = xmin;
  263. _c->viewport.ymin = ymin;
  264. _c->viewport.xsize = xsize;
  265. _c->viewport.ysize = ysize;
  266. set_scissor(0.0f, 1.0f, 0.0f, 1.0f);
  267. nassertv(xmin >= 0 && xmin < _c->zb->xsize &&
  268. ymin >= 0 && ymin < _c->zb->ysize &&
  269. xmin + xsize >= 0 && xmin + xsize <= _c->zb->xsize &&
  270. ymin + ysize >= 0 && ymin + ysize <= _c->zb->ysize);
  271. }
  272. ////////////////////////////////////////////////////////////////////
  273. // Function: TinyGraphicsStateGuardian::calc_projection_mat
  274. // Access: Public, Virtual
  275. // Description: Given a lens, calculates the appropriate projection
  276. // matrix for use with this gsg. Note that the
  277. // projection matrix depends a lot upon the coordinate
  278. // system of the rendering API.
  279. //
  280. // The return value is a TransformState if the lens is
  281. // acceptable, NULL if it is not.
  282. ////////////////////////////////////////////////////////////////////
  283. CPT(TransformState) TinyGraphicsStateGuardian::
  284. calc_projection_mat(const Lens *lens) {
  285. if (lens == (Lens *)NULL) {
  286. return NULL;
  287. }
  288. if (!lens->is_linear()) {
  289. return NULL;
  290. }
  291. // The projection matrix must always be right-handed Y-up, even if
  292. // our coordinate system of choice is otherwise, because certain GL
  293. // calls (specifically glTexGen(GL_SPHERE_MAP)) assume this kind of
  294. // a coordinate system. Sigh. In order to implement a Z-up (or
  295. // other arbitrary) coordinate system, we'll use a Y-up projection
  296. // matrix, and store the conversion to our coordinate system of
  297. // choice in the modelview matrix.
  298. LMatrix4 result =
  299. LMatrix4::convert_mat(CS_yup_right, _current_lens->get_coordinate_system()) *
  300. lens->get_projection_mat(_current_stereo_channel);
  301. if (_scene_setup->get_inverted()) {
  302. // If the scene is supposed to be inverted, then invert the
  303. // projection matrix.
  304. result *= LMatrix4::scale_mat(1.0f, -1.0f, 1.0f);
  305. }
  306. return TransformState::make_mat(result);
  307. }
  308. ////////////////////////////////////////////////////////////////////
  309. // Function: TinyGraphicsStateGuardian::prepare_lens
  310. // Access: Public, Virtual
  311. // Description: Makes the current lens (whichever lens was most
  312. // recently specified with set_scene()) active, so
  313. // that it will transform future rendered geometry.
  314. // Normally this is only called from the draw process,
  315. // and usually it is called by set_scene().
  316. //
  317. // The return value is true if the lens is acceptable,
  318. // false if it is not.
  319. ////////////////////////////////////////////////////////////////////
  320. bool TinyGraphicsStateGuardian::
  321. prepare_lens() {
  322. _transform_stale = true;
  323. return true;
  324. }
  325. ////////////////////////////////////////////////////////////////////
  326. // Function: GraphicsStateGuardian::begin_frame
  327. // Access: Public, Virtual
  328. // Description: Called before each frame is rendered, to allow the
  329. // GSG a chance to do any internal cleanup before
  330. // beginning the frame.
  331. //
  332. // The return value is true if successful (in which case
  333. // the frame will be drawn and end_frame() will be
  334. // called later), or false if unsuccessful (in which
  335. // case nothing will be drawn and end_frame() will not
  336. // be called).
  337. ////////////////////////////////////////////////////////////////////
  338. bool TinyGraphicsStateGuardian::
  339. begin_frame(Thread *current_thread) {
  340. if (!GraphicsStateGuardian::begin_frame(current_thread)) {
  341. return false;
  342. }
  343. _c->zb = _current_frame_buffer;
  344. #ifdef DO_PSTATS
  345. _vertices_immediate_pcollector.clear_level();
  346. _pixel_count_white_untextured_pcollector.clear_level();
  347. _pixel_count_flat_untextured_pcollector.clear_level();
  348. _pixel_count_smooth_untextured_pcollector.clear_level();
  349. _pixel_count_white_textured_pcollector.clear_level();
  350. _pixel_count_flat_textured_pcollector.clear_level();
  351. _pixel_count_smooth_textured_pcollector.clear_level();
  352. _pixel_count_white_perspective_pcollector.clear_level();
  353. _pixel_count_flat_perspective_pcollector.clear_level();
  354. _pixel_count_smooth_perspective_pcollector.clear_level();
  355. _pixel_count_smooth_multitex2_pcollector.clear_level();
  356. _pixel_count_smooth_multitex3_pcollector.clear_level();
  357. #endif
  358. return true;
  359. }
  360. ////////////////////////////////////////////////////////////////////
  361. // Function: GraphicsStateGuardian::begin_scene
  362. // Access: Public, Virtual
  363. // Description: Called between begin_frame() and end_frame() to mark
  364. // the beginning of drawing commands for a "scene"
  365. // (usually a particular DisplayRegion) within a frame.
  366. // All 3-D drawing commands, except the clear operation,
  367. // must be enclosed within begin_scene() .. end_scene().
  368. //
  369. // The return value is true if successful (in which case
  370. // the scene will be drawn and end_scene() will be
  371. // called later), or false if unsuccessful (in which
  372. // case nothing will be drawn and end_scene() will not
  373. // be called).
  374. ////////////////////////////////////////////////////////////////////
  375. bool TinyGraphicsStateGuardian::
  376. begin_scene() {
  377. return GraphicsStateGuardian::begin_scene();
  378. }
  379. ////////////////////////////////////////////////////////////////////
  380. // Function: TinyGraphicsStateGuardian::end_scene
  381. // Access: Protected, Virtual
  382. // Description: Called between begin_frame() and end_frame() to mark
  383. // the end of drawing commands for a "scene" (usually a
  384. // particular DisplayRegion) within a frame. All 3-D
  385. // drawing commands, except the clear operation, must be
  386. // enclosed within begin_scene() .. end_scene().
  387. ////////////////////////////////////////////////////////////////////
  388. void TinyGraphicsStateGuardian::
  389. end_scene() {
  390. if (_c->zb == _aux_frame_buffer) {
  391. // Copy the aux frame buffer into the main scene now, zooming it
  392. // up to the appropriate size.
  393. int xmin, ymin, xsize, ysize;
  394. _current_display_region->get_region_pixels_i(xmin, ymin, xsize, ysize);
  395. PN_stdfloat pixel_factor = _current_display_region->get_pixel_factor();
  396. int fb_xsize = int(xsize * pixel_factor);
  397. int fb_ysize = int(ysize * pixel_factor);
  398. ZB_zoomFrameBuffer(_current_frame_buffer, xmin, ymin, xsize, ysize,
  399. _aux_frame_buffer, 0, 0, fb_xsize, fb_ysize);
  400. _c->zb = _current_frame_buffer;
  401. }
  402. // Clear the lighting state.
  403. clear_light_state();
  404. _plights.clear();
  405. _dlights.clear();
  406. _slights.clear();
  407. GraphicsStateGuardian::end_scene();
  408. }
  409. ////////////////////////////////////////////////////////////////////
  410. // Function: TinyGraphicsStateGuardian::end_frame
  411. // Access: Public, Virtual
  412. // Description: Called after each frame is rendered, to allow the
  413. // GSG a chance to do any internal cleanup after
  414. // rendering the frame, and before the window flips.
  415. ////////////////////////////////////////////////////////////////////
  416. void TinyGraphicsStateGuardian::
  417. end_frame(Thread *current_thread) {
  418. GraphicsStateGuardian::end_frame(current_thread);
  419. #ifndef NDEBUG
  420. static ConfigVariableBool td_show_zbuffer
  421. ("td-show-zbuffer", false,
  422. PRC_DESC("Set this true to draw the ZBuffer instead of the visible buffer, when rendering with tinydisplay. This is useful to aid debugging the ZBuffer"));
  423. if (td_show_zbuffer) {
  424. PIXEL *tp = _current_frame_buffer->pbuf;
  425. ZPOINT *tz = _current_frame_buffer->zbuf;
  426. for (int yi = 0; yi < _current_frame_buffer->ysize; ++yi) {
  427. for (int xi = 0; xi < _current_frame_buffer->xsize; ++xi) {
  428. (*tp) = (int)(*tz);
  429. ++tz;
  430. ++tp;
  431. }
  432. }
  433. }
  434. #endif // NDEBUG
  435. #ifdef DO_PSTATS
  436. // Flush any PCollectors specific to this kind of GSG.
  437. _vertices_immediate_pcollector.flush_level();
  438. _pixel_count_white_untextured_pcollector.flush_level();
  439. _pixel_count_flat_untextured_pcollector.flush_level();
  440. _pixel_count_smooth_untextured_pcollector.flush_level();
  441. _pixel_count_white_textured_pcollector.flush_level();
  442. _pixel_count_flat_textured_pcollector.flush_level();
  443. _pixel_count_smooth_textured_pcollector.flush_level();
  444. _pixel_count_white_perspective_pcollector.flush_level();
  445. _pixel_count_flat_perspective_pcollector.flush_level();
  446. _pixel_count_smooth_perspective_pcollector.flush_level();
  447. _pixel_count_smooth_multitex2_pcollector.flush_level();
  448. _pixel_count_smooth_multitex3_pcollector.flush_level();
  449. #endif // DO_PSTATS
  450. }
  451. ////////////////////////////////////////////////////////////////////
  452. // Function: TinyGraphicsStateGuardian::begin_draw_primitives
  453. // Access: Public, Virtual
  454. // Description: Called before a sequence of draw_primitive()
  455. // functions are called, this should prepare the vertex
  456. // data for rendering. It returns true if the vertices
  457. // are ok, false to abort this group of primitives.
  458. ////////////////////////////////////////////////////////////////////
  459. bool TinyGraphicsStateGuardian::
  460. begin_draw_primitives(const GeomPipelineReader *geom_reader,
  461. const GeomMunger *munger,
  462. const GeomVertexDataPipelineReader *data_reader,
  463. bool force) {
  464. #ifndef NDEBUG
  465. if (tinydisplay_cat.is_spam()) {
  466. tinydisplay_cat.spam() << "begin_draw_primitives: " << *(data_reader->get_object()) << "\n";
  467. }
  468. #endif // NDEBUG
  469. if (!GraphicsStateGuardian::begin_draw_primitives(geom_reader, munger, data_reader, force)) {
  470. return false;
  471. }
  472. nassertr(_data_reader != (GeomVertexDataPipelineReader *)NULL, false);
  473. PStatTimer timer(_draw_transform_pcollector);
  474. // Set up the proper transform.
  475. if (_data_reader->is_vertex_transformed()) {
  476. // If the vertex data claims to be already transformed into clip
  477. // coordinates, wipe out the current projection and modelview
  478. // matrix (so we don't attempt to transform it again).
  479. const TransformState *ident = TransformState::make_identity();
  480. load_matrix(&_c->matrix_model_view, ident);
  481. load_matrix(&_c->matrix_projection, _scissor_mat);
  482. load_matrix(&_c->matrix_model_view_inv, ident);
  483. load_matrix(&_c->matrix_model_projection, _scissor_mat);
  484. _c->matrix_model_projection_no_w_transform = 1;
  485. _transform_stale = true;
  486. } else if (_transform_stale) {
  487. // Load the actual transform.
  488. CPT(TransformState) scissor_proj_mat = _scissor_mat->compose(_projection_mat);
  489. if (_c->lighting_enabled) {
  490. // With the lighting equation, we need to keep the modelview and
  491. // projection matrices separate.
  492. load_matrix(&_c->matrix_model_view, _internal_transform);
  493. load_matrix(&_c->matrix_projection, scissor_proj_mat);
  494. /* precompute inverse modelview */
  495. M4 tmp;
  496. gl_M4_Inv(&tmp, &_c->matrix_model_view);
  497. gl_M4_Transpose(&_c->matrix_model_view_inv, &tmp);
  498. }
  499. // Compose the modelview and projection matrices.
  500. load_matrix(&_c->matrix_model_projection,
  501. scissor_proj_mat->compose(_internal_transform));
  502. /* test to accelerate computation */
  503. _c->matrix_model_projection_no_w_transform = 0;
  504. PN_stdfloat *m = &_c->matrix_model_projection.m[0][0];
  505. if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) {
  506. _c->matrix_model_projection_no_w_transform = 1;
  507. }
  508. _transform_stale = false;
  509. }
  510. // Figure out the subset of vertices we will be using in this
  511. // operation.
  512. int num_vertices = data_reader->get_num_rows();
  513. _min_vertex = num_vertices;
  514. _max_vertex = 0;
  515. int num_prims = geom_reader->get_num_primitives();
  516. int i;
  517. for (i = 0; i < num_prims; ++i) {
  518. CPT(GeomPrimitive) prim = geom_reader->get_primitive(i);
  519. int nv = prim->get_min_vertex();
  520. _min_vertex = min(_min_vertex, nv);
  521. int xv = prim->get_max_vertex();
  522. _max_vertex = max(_max_vertex, xv);
  523. }
  524. if (_min_vertex > _max_vertex) {
  525. return false;
  526. }
  527. // Now copy all of those vertices into our working table,
  528. // transforming into screen space them as we go.
  529. int num_used_vertices = _max_vertex - _min_vertex + 1;
  530. if (_vertices_size < num_used_vertices) {
  531. if (_vertices_size == 0) {
  532. _vertices_size = 1;
  533. }
  534. while (_vertices_size < num_used_vertices) {
  535. _vertices_size *= 2;
  536. }
  537. if (_vertices != (GLVertex *)NULL) {
  538. PANDA_FREE_ARRAY(_vertices);
  539. }
  540. _vertices = (GLVertex *)PANDA_MALLOC_ARRAY(_vertices_size * sizeof(GLVertex));
  541. }
  542. GeomVertexReader rcolor, rnormal;
  543. // We now support up to 3-stage multitexturing.
  544. GenTexcoordFunc *texgen_func[MAX_TEXTURE_STAGES];
  545. TexCoordData tcdata[MAX_TEXTURE_STAGES];
  546. const TexGenAttrib *target_tex_gen = DCAST(TexGenAttrib, _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()));
  547. const TexMatrixAttrib *target_tex_matrix = DCAST(TexMatrixAttrib, _target_rs->get_attrib_def(TexMatrixAttrib::get_class_slot()));
  548. int max_stage_index = _target_texture->get_num_on_ff_stages();
  549. for (int si = 0; si < max_stage_index; ++si) {
  550. TextureStage *stage = _target_texture->get_on_ff_stage(si);
  551. switch (target_tex_gen->get_mode(stage)) {
  552. case TexGenAttrib::M_eye_sphere_map:
  553. tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_normal(),
  554. force);
  555. tcdata[si]._r2 = GeomVertexReader(data_reader, InternalName::get_vertex(),
  556. force);
  557. texgen_func[si] = &texgen_sphere_map;
  558. tcdata[si]._mat = _internal_transform->get_mat();
  559. break;
  560. case TexGenAttrib::M_eye_position:
  561. tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_vertex(),
  562. force);
  563. texgen_func[si] = &texgen_texmat;
  564. {
  565. CPT(TransformState) eye_transform =
  566. _cs_transform->invert_compose(_internal_transform);
  567. tcdata[si]._mat = eye_transform->get_mat();
  568. }
  569. if (target_tex_matrix->has_stage(stage)) {
  570. tcdata[si]._mat = tcdata[si]._mat * target_tex_matrix->get_mat(stage);
  571. }
  572. break;
  573. case TexGenAttrib::M_world_position:
  574. tcdata[si]._r1 = GeomVertexReader(data_reader, InternalName::get_vertex(),
  575. force);
  576. texgen_func[si] = &texgen_texmat;
  577. {
  578. CPT(TransformState) render_transform =
  579. _cs_transform->compose(_scene_setup->get_world_transform());
  580. CPT(TransformState) world_inv_transform =
  581. render_transform->invert_compose(_internal_transform);
  582. tcdata[si]._mat = world_inv_transform->get_mat();
  583. }
  584. if (target_tex_matrix->has_stage(stage)) {
  585. tcdata[si]._mat = tcdata[si]._mat * target_tex_matrix->get_mat(stage);
  586. }
  587. break;
  588. default:
  589. // Fall through: use the standard texture coordinates.
  590. tcdata[si]._r1 = GeomVertexReader(data_reader, stage->get_texcoord_name(),
  591. force);
  592. texgen_func[si] = &texgen_simple;
  593. if (target_tex_matrix->has_stage(stage)) {
  594. texgen_func[si] = &texgen_texmat;
  595. tcdata[si]._mat = target_tex_matrix->get_mat(stage);
  596. }
  597. break;
  598. }
  599. tcdata[si]._r1.set_row_unsafe(_min_vertex);
  600. tcdata[si]._r2.set_row_unsafe(_min_vertex);
  601. if (!tcdata[si]._r1.has_column()) {
  602. texgen_func[si] = &texgen_null;
  603. }
  604. }
  605. bool needs_color = false;
  606. if (_vertex_colors_enabled) {
  607. rcolor = GeomVertexReader(data_reader, InternalName::get_color(), force);
  608. rcolor.set_row_unsafe(_min_vertex);
  609. needs_color = rcolor.has_column();
  610. }
  611. if (!needs_color) {
  612. const LColor &d = _scene_graph_color;
  613. const LColor &s = _current_color_scale;
  614. _c->current_color.v[0] = d[0] * s[0];
  615. _c->current_color.v[1] = d[1] * s[1];
  616. _c->current_color.v[2] = d[2] * s[2];
  617. _c->current_color.v[3] = d[3] * s[3];
  618. }
  619. bool needs_normal = false;
  620. if (_c->lighting_enabled) {
  621. rnormal = GeomVertexReader(data_reader, InternalName::get_normal(), force);
  622. rnormal.set_row_unsafe(_min_vertex);
  623. needs_normal = rnormal.has_column();
  624. }
  625. GeomVertexReader rvertex(data_reader, InternalName::get_vertex(), force);
  626. rvertex.set_row_unsafe(_min_vertex);
  627. if (!rvertex.has_column()) {
  628. // Whoops, guess the vertex data isn't resident.
  629. return false;
  630. }
  631. if (!needs_color && _color_material_flags) {
  632. if (_color_material_flags & CMF_ambient) {
  633. _c->materials[0].ambient = _c->current_color;
  634. _c->materials[1].ambient = _c->current_color;
  635. }
  636. if (_color_material_flags & CMF_diffuse) {
  637. _c->materials[0].diffuse = _c->current_color;
  638. _c->materials[1].diffuse = _c->current_color;
  639. }
  640. }
  641. if (_texturing_state != 0 && _texture_replace) {
  642. // We don't need the vertex color or lighting calculation after
  643. // all, since the current texture will just hide all of that.
  644. needs_color = false;
  645. needs_normal = false;
  646. }
  647. bool lighting_enabled = (needs_normal && _c->lighting_enabled);
  648. for (i = 0; i < num_used_vertices; ++i) {
  649. GLVertex *v = &_vertices[i];
  650. const LVecBase4 &d = rvertex.get_data4();
  651. v->coord.v[0] = d[0];
  652. v->coord.v[1] = d[1];
  653. v->coord.v[2] = d[2];
  654. v->coord.v[3] = d[3];
  655. // Texture coordinates.
  656. for (int si = 0; si < max_stage_index; ++si) {
  657. LTexCoord d;
  658. (*texgen_func[si])(v->tex_coord[si], tcdata[si]);
  659. }
  660. if (needs_color) {
  661. const LColor &d = rcolor.get_data4();
  662. const LColor &s = _current_color_scale;
  663. _c->current_color.v[0] = d[0] * s[0];
  664. _c->current_color.v[1] = d[1] * s[1];
  665. _c->current_color.v[2] = d[2] * s[2];
  666. _c->current_color.v[3] = d[3] * s[3];
  667. if (_color_material_flags) {
  668. if (_color_material_flags & CMF_ambient) {
  669. _c->materials[0].ambient = _c->current_color;
  670. _c->materials[1].ambient = _c->current_color;
  671. }
  672. if (_color_material_flags & CMF_diffuse) {
  673. _c->materials[0].diffuse = _c->current_color;
  674. _c->materials[1].diffuse = _c->current_color;
  675. }
  676. }
  677. }
  678. v->color = _c->current_color;
  679. if (lighting_enabled) {
  680. const LVecBase3 &d = rnormal.get_data3();
  681. _c->current_normal.v[0] = d[0];
  682. _c->current_normal.v[1] = d[1];
  683. _c->current_normal.v[2] = d[2];
  684. _c->current_normal.v[3] = 0.0f;
  685. gl_vertex_transform(_c, v);
  686. gl_shade_vertex(_c, v);
  687. } else {
  688. gl_vertex_transform(_c, v);
  689. }
  690. if (v->clip_code == 0) {
  691. gl_transform_to_viewport(_c, v);
  692. }
  693. v->edge_flag = 1;
  694. }
  695. // Set up the appropriate function callback for filling triangles,
  696. // according to the current state.
  697. int depth_write_state = 0; // zon
  698. const DepthWriteAttrib *target_depth_write = DCAST(DepthWriteAttrib, _target_rs->get_attrib_def(DepthWriteAttrib::get_class_slot()));
  699. if (target_depth_write->get_mode() != DepthWriteAttrib::M_on) {
  700. depth_write_state = 1; // zoff
  701. }
  702. int color_write_state = 0; // cstore
  703. const ColorWriteAttrib *target_color_write = DCAST(ColorWriteAttrib, _target_rs->get_attrib_def(ColorWriteAttrib::get_class_slot()));
  704. unsigned int color_channels =
  705. target_color_write->get_channels() & _color_write_mask;
  706. if (color_channels != ColorWriteAttrib::C_all) {
  707. // Implement a color mask.
  708. int op_a = get_color_blend_op(ColorBlendAttrib::O_one);
  709. int op_b = get_color_blend_op(ColorBlendAttrib::O_zero);
  710. _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
  711. color_write_state = 2; // cgeneral
  712. }
  713. const TransparencyAttrib *target_transparency = DCAST(TransparencyAttrib, _target_rs->get_attrib_def(TransparencyAttrib::get_class_slot()));
  714. switch (target_transparency->get_mode()) {
  715. case TransparencyAttrib::M_alpha:
  716. case TransparencyAttrib::M_dual:
  717. color_write_state = 1; // cblend
  718. if (color_channels != ColorWriteAttrib::C_all) {
  719. // Implement a color mask, with alpha blending.
  720. int op_a = get_color_blend_op(ColorBlendAttrib::O_incoming_alpha);
  721. int op_b = get_color_blend_op(ColorBlendAttrib::O_one_minus_incoming_alpha);
  722. _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
  723. color_write_state = 2; // cgeneral
  724. }
  725. break;
  726. default:
  727. break;
  728. }
  729. const ColorBlendAttrib *target_color_blend = DCAST(ColorBlendAttrib, _target_rs->get_attrib_def(ColorBlendAttrib::get_class_slot()));
  730. if (target_color_blend->get_mode() == ColorBlendAttrib::M_add) {
  731. // If we have a color blend set that we can support, it overrides
  732. // the transparency set.
  733. int op_a = get_color_blend_op(target_color_blend->get_operand_a());
  734. int op_b = get_color_blend_op(target_color_blend->get_operand_b());
  735. _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
  736. LColor c = target_color_blend->get_color();
  737. _c->zb->blend_r = (int)(c[0] * ZB_POINT_RED_MAX);
  738. _c->zb->blend_g = (int)(c[1] * ZB_POINT_GREEN_MAX);
  739. _c->zb->blend_b = (int)(c[2] * ZB_POINT_BLUE_MAX);
  740. _c->zb->blend_a = (int)(c[3] * ZB_POINT_ALPHA_MAX);
  741. color_write_state = 2; // cgeneral
  742. }
  743. if (color_channels == ColorWriteAttrib::C_off) {
  744. color_write_state = 3; // coff
  745. }
  746. int alpha_test_state = 0; // anone
  747. const AlphaTestAttrib *target_alpha_test = DCAST(AlphaTestAttrib, _target_rs->get_attrib_def(AlphaTestAttrib::get_class_slot()));
  748. switch (target_alpha_test->get_mode()) {
  749. case AlphaTestAttrib::M_none:
  750. case AlphaTestAttrib::M_never:
  751. case AlphaTestAttrib::M_always:
  752. case AlphaTestAttrib::M_equal:
  753. case AlphaTestAttrib::M_not_equal:
  754. alpha_test_state = 0; // anone
  755. break;
  756. case AlphaTestAttrib::M_less:
  757. case AlphaTestAttrib::M_less_equal:
  758. alpha_test_state = 1; // aless
  759. _c->zb->reference_alpha = (int)(target_alpha_test->get_reference_alpha() * ZB_POINT_ALPHA_MAX);
  760. break;
  761. case AlphaTestAttrib::M_greater:
  762. case AlphaTestAttrib::M_greater_equal:
  763. alpha_test_state = 2; // amore
  764. _c->zb->reference_alpha = (int)(target_alpha_test->get_reference_alpha() * ZB_POINT_ALPHA_MAX);
  765. break;
  766. }
  767. int depth_test_state = 1; // zless
  768. _c->depth_test = 1; // set this for ZB_line
  769. const DepthTestAttrib *target_depth_test = DCAST(DepthTestAttrib, _target_rs->get_attrib_def(DepthTestAttrib::get_class_slot()));
  770. if (target_depth_test->get_mode() == DepthTestAttrib::M_none) {
  771. depth_test_state = 0; // zless
  772. _c->depth_test = 0;
  773. }
  774. const ShadeModelAttrib *target_shade_model = DCAST(ShadeModelAttrib, _target_rs->get_attrib_def(ShadeModelAttrib::get_class_slot()));
  775. ShadeModelAttrib::Mode shade_model = target_shade_model->get_mode();
  776. if (!needs_normal && !needs_color) {
  777. // With no per-vertex lighting, and no per-vertex colors, we might
  778. // as well use the flat shading model.
  779. shade_model = ShadeModelAttrib::M_flat;
  780. }
  781. int shade_model_state = 2; // smooth
  782. _c->smooth_shade_model = true;
  783. if (shade_model == ShadeModelAttrib::M_flat) {
  784. _c->smooth_shade_model = false;
  785. shade_model_state = 1; // flat
  786. if (_c->current_color.v[0] == 1.0f &&
  787. _c->current_color.v[1] == 1.0f &&
  788. _c->current_color.v[2] == 1.0f &&
  789. _c->current_color.v[3] == 1.0f) {
  790. shade_model_state = 0; // white
  791. }
  792. }
  793. int texturing_state = _texturing_state;
  794. int texfilter_state = 0; // tnearest
  795. if (texturing_state > 0) {
  796. texfilter_state = _texfilter_state;
  797. if (texturing_state < 3 &&
  798. (_c->matrix_model_projection_no_w_transform || _filled_flat)) {
  799. // Don't bother with the perspective-correct algorithm if we're
  800. // under an orthonormal lens, e.g. render2d; or if
  801. // RenderMode::M_filled_flat is in effect.
  802. texturing_state = 1; // textured (not perspective correct)
  803. }
  804. if (_texture_replace) {
  805. // If we're completely replacing the underlying color, then it
  806. // doesn't matter what the color is.
  807. shade_model_state = 0;
  808. }
  809. }
  810. _c->zb_fill_tri = fill_tri_funcs[depth_write_state][color_write_state][alpha_test_state][depth_test_state][texfilter_state][shade_model_state][texturing_state];
  811. #ifdef DO_PSTATS
  812. pixel_count_white_untextured = 0;
  813. pixel_count_flat_untextured = 0;
  814. pixel_count_smooth_untextured = 0;
  815. pixel_count_white_textured = 0;
  816. pixel_count_flat_textured = 0;
  817. pixel_count_smooth_textured = 0;
  818. pixel_count_white_perspective = 0;
  819. pixel_count_flat_perspective = 0;
  820. pixel_count_smooth_perspective = 0;
  821. pixel_count_smooth_multitex2 = 0;
  822. pixel_count_smooth_multitex3 = 0;
  823. #endif // DO_PSTATS
  824. return true;
  825. }
  826. ////////////////////////////////////////////////////////////////////
  827. // Function: TinyGraphicsStateGuardian::draw_triangles
  828. // Access: Public, Virtual
  829. // Description: Draws a series of disconnected triangles.
  830. ////////////////////////////////////////////////////////////////////
  831. bool TinyGraphicsStateGuardian::
  832. draw_triangles(const GeomPrimitivePipelineReader *reader, bool force) {
  833. PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
  834. #ifndef NDEBUG
  835. if (tinydisplay_cat.is_spam()) {
  836. tinydisplay_cat.spam() << "draw_triangles: " << *(reader->get_object()) << "\n";
  837. }
  838. #endif // NDEBUG
  839. int num_vertices = reader->get_num_vertices();
  840. _vertices_tri_pcollector.add_level(num_vertices);
  841. if (reader->is_indexed()) {
  842. switch (reader->get_index_type()) {
  843. case Geom::NT_uint8:
  844. {
  845. PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
  846. if (index == NULL) {
  847. return false;
  848. }
  849. for (int i = 0; i < num_vertices; i += 3) {
  850. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  851. GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
  852. GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
  853. gl_draw_triangle(_c, v0, v1, v2);
  854. }
  855. }
  856. break;
  857. case Geom::NT_uint16:
  858. {
  859. PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
  860. if (index == NULL) {
  861. return false;
  862. }
  863. for (int i = 0; i < num_vertices; i += 3) {
  864. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  865. GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
  866. GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
  867. gl_draw_triangle(_c, v0, v1, v2);
  868. }
  869. }
  870. break;
  871. case Geom::NT_uint32:
  872. {
  873. PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
  874. if (index == NULL) {
  875. return false;
  876. }
  877. for (int i = 0; i < num_vertices; i += 3) {
  878. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  879. GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
  880. GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
  881. gl_draw_triangle(_c, v0, v1, v2);
  882. }
  883. }
  884. break;
  885. default:
  886. break;
  887. }
  888. } else {
  889. int delta = reader->get_first_vertex() - _min_vertex;
  890. for (int vi = 0; vi < num_vertices; vi += 3) {
  891. GLVertex *v0 = &_vertices[vi + delta];
  892. GLVertex *v1 = &_vertices[vi + delta + 1];
  893. GLVertex *v2 = &_vertices[vi + delta + 2];
  894. gl_draw_triangle(_c, v0, v1, v2);
  895. }
  896. }
  897. return true;
  898. }
  899. ////////////////////////////////////////////////////////////////////
  900. // Function: TinyGraphicsStateGuardian::draw_tristrips
  901. // Access: Public, Virtual
  902. // Description: Draws a series of triangle strips.
  903. ////////////////////////////////////////////////////////////////////
  904. bool TinyGraphicsStateGuardian::
  905. draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force) {
  906. PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
  907. #ifndef NDEBUG
  908. if (tinydisplay_cat.is_spam()) {
  909. tinydisplay_cat.spam() << "draw_tristrips: " << *(reader->get_object()) << "\n";
  910. }
  911. #endif // NDEBUG
  912. // Send the individual triangle strips, stepping over the
  913. // degenerate vertices.
  914. CPTA_int ends = reader->get_ends();
  915. _primitive_batches_tristrip_pcollector.add_level(ends.size());
  916. if (reader->is_indexed()) {
  917. unsigned int start = 0;
  918. for (size_t i = 0; i < ends.size(); i++) {
  919. _vertices_tristrip_pcollector.add_level(ends[i] - start);
  920. int end = ends[i];
  921. nassertr(end - start >= 3, false);
  922. switch (reader->get_index_type()) {
  923. case Geom::NT_uint8:
  924. {
  925. PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
  926. if (index == NULL) {
  927. return false;
  928. }
  929. GLVertex *v0 = &_vertices[index[start] - _min_vertex];
  930. GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
  931. bool reversed = false;
  932. for (int vi = start + 2; vi < end; ++vi) {
  933. GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
  934. if (reversed) {
  935. gl_draw_triangle(_c, v1, v0, v2);
  936. reversed = false;
  937. } else {
  938. gl_draw_triangle(_c, v0, v1, v2);
  939. reversed = true;
  940. }
  941. v0 = v1;
  942. v1 = v2;
  943. }
  944. }
  945. break;
  946. case Geom::NT_uint16:
  947. {
  948. PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
  949. if (index == NULL) {
  950. return false;
  951. }
  952. GLVertex *v0 = &_vertices[index[start] - _min_vertex];
  953. GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
  954. bool reversed = false;
  955. for (int vi = start + 2; vi < end; ++vi) {
  956. GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
  957. if (reversed) {
  958. gl_draw_triangle(_c, v1, v0, v2);
  959. reversed = false;
  960. } else {
  961. gl_draw_triangle(_c, v0, v1, v2);
  962. reversed = true;
  963. }
  964. v0 = v1;
  965. v1 = v2;
  966. }
  967. }
  968. break;
  969. case Geom::NT_uint32:
  970. {
  971. PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
  972. if (index == NULL) {
  973. return false;
  974. }
  975. GLVertex *v0 = &_vertices[index[start] - _min_vertex];
  976. GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
  977. bool reversed = false;
  978. for (int vi = start + 2; vi < end; ++vi) {
  979. GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
  980. if (reversed) {
  981. gl_draw_triangle(_c, v1, v0, v2);
  982. reversed = false;
  983. } else {
  984. gl_draw_triangle(_c, v0, v1, v2);
  985. reversed = true;
  986. }
  987. v0 = v1;
  988. v1 = v2;
  989. }
  990. }
  991. break;
  992. }
  993. start = ends[i] + 2;
  994. }
  995. } else {
  996. unsigned int start = 0;
  997. int delta = reader->get_first_vertex() - _min_vertex;
  998. for (size_t i = 0; i < ends.size(); i++) {
  999. _vertices_tristrip_pcollector.add_level(ends[i] - start);
  1000. int end = ends[i];
  1001. nassertr(end - start >= 3, false);
  1002. GLVertex *v0 = &_vertices[start + delta];
  1003. GLVertex *v1 = &_vertices[start + delta + 1];
  1004. bool reversed = false;
  1005. for (int vi = start + 2; vi < end; ++vi) {
  1006. GLVertex *v2 = &_vertices[vi + delta];
  1007. if (reversed) {
  1008. gl_draw_triangle(_c, v1, v0, v2);
  1009. reversed = false;
  1010. } else {
  1011. gl_draw_triangle(_c, v0, v1, v2);
  1012. reversed = true;
  1013. }
  1014. v0 = v1;
  1015. v1 = v2;
  1016. }
  1017. start = ends[i] + 2;
  1018. }
  1019. }
  1020. return true;
  1021. }
  1022. ////////////////////////////////////////////////////////////////////
  1023. // Function: TinyGraphicsStateGuardian::draw_lines
  1024. // Access: Public, Virtual
  1025. // Description: Draws a series of disconnected line segments.
  1026. ////////////////////////////////////////////////////////////////////
  1027. bool TinyGraphicsStateGuardian::
  1028. draw_lines(const GeomPrimitivePipelineReader *reader, bool force) {
  1029. PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
  1030. #ifndef NDEBUG
  1031. if (tinydisplay_cat.is_spam()) {
  1032. tinydisplay_cat.spam() << "draw_lines: " << *(reader->get_object()) << "\n";
  1033. }
  1034. #endif // NDEBUG
  1035. int num_vertices = reader->get_num_vertices();
  1036. _vertices_other_pcollector.add_level(num_vertices);
  1037. if (reader->is_indexed()) {
  1038. switch (reader->get_index_type()) {
  1039. case Geom::NT_uint8:
  1040. {
  1041. PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
  1042. if (index == NULL) {
  1043. return false;
  1044. }
  1045. for (int i = 0; i < num_vertices; i += 2) {
  1046. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  1047. GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
  1048. gl_draw_line(_c, v0, v1);
  1049. }
  1050. }
  1051. break;
  1052. case Geom::NT_uint16:
  1053. {
  1054. PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
  1055. if (index == NULL) {
  1056. return false;
  1057. }
  1058. for (int i = 0; i < num_vertices; i += 2) {
  1059. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  1060. GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
  1061. gl_draw_line(_c, v0, v1);
  1062. }
  1063. }
  1064. break;
  1065. case Geom::NT_uint32:
  1066. {
  1067. PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
  1068. if (index == NULL) {
  1069. return false;
  1070. }
  1071. for (int i = 0; i < num_vertices; i += 2) {
  1072. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  1073. GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
  1074. gl_draw_line(_c, v0, v1);
  1075. }
  1076. }
  1077. break;
  1078. default:
  1079. break;
  1080. }
  1081. } else {
  1082. int delta = reader->get_first_vertex() - _min_vertex;
  1083. for (int vi = 0; vi < num_vertices; vi += 2) {
  1084. GLVertex *v0 = &_vertices[vi + delta];
  1085. GLVertex *v1 = &_vertices[vi + delta + 1];
  1086. gl_draw_line(_c, v0, v1);
  1087. }
  1088. }
  1089. return true;
  1090. }
  1091. ////////////////////////////////////////////////////////////////////
  1092. // Function: TinyGraphicsStateGuardian::draw_points
  1093. // Access: Public, Virtual
  1094. // Description: Draws a series of disconnected points.
  1095. ////////////////////////////////////////////////////////////////////
  1096. bool TinyGraphicsStateGuardian::
  1097. draw_points(const GeomPrimitivePipelineReader *reader, bool force) {
  1098. PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
  1099. #ifndef NDEBUG
  1100. if (tinydisplay_cat.is_spam()) {
  1101. tinydisplay_cat.spam() << "draw_points: " << *(reader->get_object()) << "\n";
  1102. }
  1103. #endif // NDEBUG
  1104. int num_vertices = reader->get_num_vertices();
  1105. _vertices_other_pcollector.add_level(num_vertices);
  1106. if (reader->is_indexed()) {
  1107. switch (reader->get_index_type()) {
  1108. case Geom::NT_uint8:
  1109. {
  1110. PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
  1111. if (index == NULL) {
  1112. return false;
  1113. }
  1114. for (int i = 0; i < num_vertices; ++i) {
  1115. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  1116. gl_draw_point(_c, v0);
  1117. }
  1118. }
  1119. break;
  1120. case Geom::NT_uint16:
  1121. {
  1122. PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
  1123. if (index == NULL) {
  1124. return false;
  1125. }
  1126. for (int i = 0; i < num_vertices; ++i) {
  1127. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  1128. gl_draw_point(_c, v0);
  1129. }
  1130. }
  1131. break;
  1132. case Geom::NT_uint32:
  1133. {
  1134. PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
  1135. if (index == NULL) {
  1136. return false;
  1137. }
  1138. for (int i = 0; i < num_vertices; ++i) {
  1139. GLVertex *v0 = &_vertices[index[i] - _min_vertex];
  1140. gl_draw_point(_c, v0);
  1141. }
  1142. }
  1143. break;
  1144. default:
  1145. break;
  1146. }
  1147. } else {
  1148. int delta = reader->get_first_vertex() - _min_vertex;
  1149. for (int vi = 0; vi < num_vertices; ++vi) {
  1150. GLVertex *v0 = &_vertices[vi + delta];
  1151. gl_draw_point(_c, v0);
  1152. }
  1153. }
  1154. return true;
  1155. }
  1156. ////////////////////////////////////////////////////////////////////
  1157. // Function: TinyGraphicsStateGuardian::end_draw_primitives()
  1158. // Access: Public, Virtual
  1159. // Description: Called after a sequence of draw_primitive()
  1160. // functions are called, this should do whatever cleanup
  1161. // is appropriate.
  1162. ////////////////////////////////////////////////////////////////////
  1163. void TinyGraphicsStateGuardian::
  1164. end_draw_primitives() {
  1165. #ifdef DO_PSTATS
  1166. _pixel_count_white_untextured_pcollector.add_level(pixel_count_white_untextured);
  1167. _pixel_count_flat_untextured_pcollector.add_level(pixel_count_flat_untextured);
  1168. _pixel_count_smooth_untextured_pcollector.add_level(pixel_count_smooth_untextured);
  1169. _pixel_count_white_textured_pcollector.add_level(pixel_count_white_textured);
  1170. _pixel_count_flat_textured_pcollector.add_level(pixel_count_flat_textured);
  1171. _pixel_count_smooth_textured_pcollector.add_level(pixel_count_smooth_textured);
  1172. _pixel_count_white_perspective_pcollector.add_level(pixel_count_white_perspective);
  1173. _pixel_count_flat_perspective_pcollector.add_level(pixel_count_flat_perspective);
  1174. _pixel_count_smooth_perspective_pcollector.add_level(pixel_count_smooth_perspective);
  1175. _pixel_count_smooth_multitex2_pcollector.add_level(pixel_count_smooth_multitex2);
  1176. _pixel_count_smooth_multitex3_pcollector.add_level(pixel_count_smooth_multitex3);
  1177. #endif // DO_PSTATS
  1178. GraphicsStateGuardian::end_draw_primitives();
  1179. }
  1180. ////////////////////////////////////////////////////////////////////
  1181. // Function: TinyGraphicsStateGuardian::framebuffer_copy_to_texture
  1182. // Access: Public, Virtual
  1183. // Description: Copy the pixels within the indicated display
  1184. // region from the framebuffer into texture memory.
  1185. //
  1186. // If z > -1, it is the cube map index into which to
  1187. // copy.
  1188. ////////////////////////////////////////////////////////////////////
  1189. bool TinyGraphicsStateGuardian::
  1190. framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr,
  1191. const RenderBuffer &rb) {
  1192. nassertr(tex != NULL && dr != NULL, false);
  1193. int xo, yo, w, h;
  1194. dr->get_region_pixels_i(xo, yo, w, h);
  1195. tex->setup_2d_texture(w, h, Texture::T_unsigned_byte, Texture::F_rgba);
  1196. int view = dr->get_tex_view_offset();
  1197. TextureContext *tc = tex->prepare_now(view, get_prepared_objects(), this);
  1198. nassertr(tc != (TextureContext *)NULL, false);
  1199. TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
  1200. GLTexture *gltex = &gtc->_gltex;
  1201. if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), 1)) {
  1202. return false;
  1203. }
  1204. LColor border_color = tex->get_border_color();
  1205. gltex->border_color.v[0] = border_color[0];
  1206. gltex->border_color.v[1] = border_color[1];
  1207. gltex->border_color.v[2] = border_color[2];
  1208. gltex->border_color.v[3] = border_color[3];
  1209. PIXEL *ip = gltex->levels[0].pixmap + gltex->xsize * gltex->ysize;
  1210. PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
  1211. for (int y = 0; y < gltex->ysize; ++y) {
  1212. ip -= gltex->xsize;
  1213. memcpy(ip, fo, gltex->xsize * PSZB);
  1214. fo += _c->zb->linesize / PSZB;
  1215. }
  1216. gtc->update_data_size_bytes(gltex->xsize * gltex->ysize * 4);
  1217. gtc->mark_loaded();
  1218. gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
  1219. return true;
  1220. }
  1221. ////////////////////////////////////////////////////////////////////
  1222. // Function: TinyGraphicsStateGuardian::framebuffer_copy_to_ram
  1223. // Access: Public, Virtual
  1224. // Description: Copy the pixels within the indicated display region
  1225. // from the framebuffer into system memory, not texture
  1226. // memory. Returns true on success, false on failure.
  1227. //
  1228. // This completely redefines the ram image of the
  1229. // indicated texture.
  1230. ////////////////////////////////////////////////////////////////////
  1231. bool TinyGraphicsStateGuardian::
  1232. framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr,
  1233. const RenderBuffer &rb) {
  1234. nassertr(tex != NULL && dr != NULL, false);
  1235. int xo, yo, w, h;
  1236. dr->get_region_pixels_i(xo, yo, w, h);
  1237. Texture::TextureType texture_type;
  1238. int z_size;
  1239. if (z >= 0) {
  1240. texture_type = Texture::TT_cube_map;
  1241. z_size = 6;
  1242. } else {
  1243. texture_type = Texture::TT_2d_texture;
  1244. z_size = 1;
  1245. }
  1246. Texture::ComponentType component_type = Texture::T_unsigned_byte;
  1247. Texture::Format format = Texture::F_rgba;
  1248. if (tex->get_x_size() != w || tex->get_y_size() != h ||
  1249. tex->get_z_size() != z_size ||
  1250. tex->get_component_type() != component_type ||
  1251. tex->get_format() != format ||
  1252. tex->get_texture_type() != texture_type) {
  1253. // Re-setup the texture; its properties have changed.
  1254. tex->setup_texture(texture_type, w, h, z_size,
  1255. component_type, format);
  1256. }
  1257. unsigned char *image_ptr = tex->modify_ram_image();
  1258. size_t image_size = tex->get_ram_image_size();
  1259. if (z >= 0) {
  1260. nassertr(z < tex->get_z_size(), false);
  1261. image_size = tex->get_expected_ram_page_size();
  1262. image_ptr += z * image_size;
  1263. }
  1264. PIXEL *ip = (PIXEL *)(image_ptr + image_size);
  1265. PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
  1266. for (int y = 0; y < h; ++y) {
  1267. ip -= w;
  1268. #ifndef WORDS_BIGENDIAN
  1269. // On a little-endian machine, we can copy the whole row at a time.
  1270. memcpy(ip, fo, w * PSZB);
  1271. #else
  1272. // On a big-endian machine, we have to reverse the color-component order.
  1273. const char *source = (const char *)fo;
  1274. const char *stop = (const char *)fo + w * PSZB;
  1275. char *dest = (char *)ip;
  1276. while (source < stop) {
  1277. char b = source[0];
  1278. char g = source[1];
  1279. char r = source[2];
  1280. char a = source[3];
  1281. dest[0] = a;
  1282. dest[1] = r;
  1283. dest[2] = g;
  1284. dest[3] = b;
  1285. dest += 4;
  1286. source += 4;
  1287. }
  1288. #endif
  1289. fo += _c->zb->linesize / PSZB;
  1290. }
  1291. return true;
  1292. }
  1293. ////////////////////////////////////////////////////////////////////
  1294. // Function: TinyGraphicsStateGuardian::set_state_and_transform
  1295. // Access: Public, Virtual
  1296. // Description: Simultaneously resets the render state and the
  1297. // transform state.
  1298. //
  1299. // This transform specified is the "internal" net
  1300. // transform, already converted into the GSG's internal
  1301. // coordinate space by composing it to
  1302. // get_cs_transform(). (Previously, this used to be the
  1303. // "external" net transform, with the assumption that
  1304. // that GSG would convert it internally, but that is no
  1305. // longer the case.)
  1306. //
  1307. // Special case: if (state==NULL), then the target
  1308. // state is already stored in _target.
  1309. ////////////////////////////////////////////////////////////////////
  1310. void TinyGraphicsStateGuardian::
  1311. set_state_and_transform(const RenderState *target,
  1312. const TransformState *transform) {
  1313. #ifndef NDEBUG
  1314. if (tinydisplay_cat.is_spam()) {
  1315. tinydisplay_cat.spam()
  1316. << "Setting GSG state to " << (void *)target << ":\n";
  1317. target->write(tinydisplay_cat.spam(false), 2);
  1318. transform->write(tinydisplay_cat.spam(false), 2);
  1319. }
  1320. #endif
  1321. _state_pcollector.add_level(1);
  1322. PStatTimer timer1(_draw_set_state_pcollector);
  1323. if (transform != _internal_transform) {
  1324. PStatTimer timer(_draw_set_state_transform_pcollector);
  1325. _state_pcollector.add_level(1);
  1326. _internal_transform = transform;
  1327. do_issue_transform();
  1328. }
  1329. if (target == _state_rs && (_state_mask | _inv_state_mask).is_all_on()) {
  1330. return;
  1331. }
  1332. _target_rs = target;
  1333. int color_slot = ColorAttrib::get_class_slot();
  1334. int color_scale_slot = ColorScaleAttrib::get_class_slot();
  1335. if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
  1336. _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
  1337. !_state_mask.get_bit(color_slot) ||
  1338. !_state_mask.get_bit(color_scale_slot)) {
  1339. PStatTimer timer(_draw_set_state_color_pcollector);
  1340. do_issue_color();
  1341. do_issue_color_scale();
  1342. _state_mask.set_bit(color_slot);
  1343. _state_mask.set_bit(color_scale_slot);
  1344. }
  1345. int cull_face_slot = CullFaceAttrib::get_class_slot();
  1346. if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
  1347. !_state_mask.get_bit(cull_face_slot)) {
  1348. PStatTimer timer(_draw_set_state_cull_face_pcollector);
  1349. do_issue_cull_face();
  1350. _state_mask.set_bit(cull_face_slot);
  1351. }
  1352. int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
  1353. if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
  1354. !_state_mask.get_bit(depth_offset_slot)) {
  1355. //PStatTimer timer(_draw_set_state_depth_offset_pcollector);
  1356. do_issue_depth_offset();
  1357. _state_mask.set_bit(depth_offset_slot);
  1358. }
  1359. int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
  1360. if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
  1361. !_state_mask.get_bit(rescale_normal_slot)) {
  1362. PStatTimer timer(_draw_set_state_rescale_normal_pcollector);
  1363. do_issue_rescale_normal();
  1364. _state_mask.set_bit(rescale_normal_slot);
  1365. }
  1366. int render_mode_slot = RenderModeAttrib::get_class_slot();
  1367. if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
  1368. !_state_mask.get_bit(render_mode_slot)) {
  1369. PStatTimer timer(_draw_set_state_render_mode_pcollector);
  1370. do_issue_render_mode();
  1371. _state_mask.set_bit(render_mode_slot);
  1372. }
  1373. int texture_slot = TextureAttrib::get_class_slot();
  1374. if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
  1375. !_state_mask.get_bit(texture_slot)) {
  1376. PStatTimer timer(_draw_set_state_texture_pcollector);
  1377. determine_target_texture();
  1378. do_issue_texture();
  1379. _state_mask.set_bit(texture_slot);
  1380. }
  1381. int material_slot = MaterialAttrib::get_class_slot();
  1382. if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
  1383. !_state_mask.get_bit(material_slot)) {
  1384. PStatTimer timer(_draw_set_state_material_pcollector);
  1385. do_issue_material();
  1386. _state_mask.set_bit(material_slot);
  1387. }
  1388. int light_slot = LightAttrib::get_class_slot();
  1389. if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
  1390. !_state_mask.get_bit(light_slot)) {
  1391. PStatTimer timer(_draw_set_state_light_pcollector);
  1392. do_issue_light();
  1393. _state_mask.set_bit(light_slot);
  1394. }
  1395. int scissor_slot = ScissorAttrib::get_class_slot();
  1396. if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
  1397. !_state_mask.get_bit(scissor_slot)) {
  1398. PStatTimer timer(_draw_set_state_scissor_pcollector);
  1399. do_issue_scissor();
  1400. _state_mask.set_bit(scissor_slot);
  1401. }
  1402. _state_rs = _target_rs;
  1403. }
  1404. ////////////////////////////////////////////////////////////////////
  1405. // Function: TinyGraphicsStateGuardian::prepare_texture
  1406. // Access: Public, Virtual
  1407. // Description: Creates whatever structures the GSG requires to
  1408. // represent the texture internally, and returns a
  1409. // newly-allocated TextureContext object with this data.
  1410. // It is the responsibility of the calling function to
  1411. // later call release_texture() with this same pointer
  1412. // (which will also delete the pointer).
  1413. //
  1414. // This function should not be called directly to
  1415. // prepare a texture. Instead, call Texture::prepare().
  1416. ////////////////////////////////////////////////////////////////////
  1417. TextureContext *TinyGraphicsStateGuardian::
  1418. prepare_texture(Texture *tex, int view) {
  1419. switch (tex->get_texture_type()) {
  1420. case Texture::TT_1d_texture:
  1421. case Texture::TT_2d_texture:
  1422. // These are supported.
  1423. break;
  1424. default:
  1425. // Anything else is not supported.
  1426. tinydisplay_cat.info()
  1427. << "Not loading texture " << tex->get_name() << ": "
  1428. << tex->get_texture_type() << "\n";
  1429. return NULL;
  1430. }
  1431. // Even though the texture might be compressed now, it might have an
  1432. // available uncompressed version that we can load. So don't reject
  1433. // it out-of-hand just because it's compressed.
  1434. /*
  1435. if (tex->get_ram_image_compression() != Texture::CM_off) {
  1436. tinydisplay_cat.info()
  1437. << "Not loading texture " << tex->get_name() << ": "
  1438. << tex->get_ram_image_compression() << "\n";
  1439. return NULL;
  1440. }
  1441. */
  1442. TinyTextureContext *gtc = new TinyTextureContext(_prepared_objects, tex, view);
  1443. return gtc;
  1444. }
  1445. ////////////////////////////////////////////////////////////////////
  1446. // Function: TinyGraphicsStateGuardian::update_texture
  1447. // Access: Public, Virtual
  1448. // Description: Ensures that the current Texture data is refreshed
  1449. // onto the GSG. This means updating the texture
  1450. // properties and/or re-uploading the texture image, if
  1451. // necessary. This should only be called within the
  1452. // draw thread.
  1453. //
  1454. // If force is true, this function will not return until
  1455. // the texture has been fully uploaded. If force is
  1456. // false, the function may choose to upload a simple
  1457. // version of the texture instead, if the texture is not
  1458. // fully resident (and if get_incomplete_render() is
  1459. // true).
  1460. ////////////////////////////////////////////////////////////////////
  1461. bool TinyGraphicsStateGuardian::
  1462. update_texture(TextureContext *tc, bool force) {
  1463. apply_texture(tc);
  1464. TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
  1465. GLTexture *gltex = &gtc->_gltex;
  1466. if (gtc->was_image_modified() || gltex->num_levels == 0) {
  1467. // If the texture image was modified, reload the texture.
  1468. bool okflag = upload_texture(gtc, force);
  1469. if (!okflag) {
  1470. tinydisplay_cat.error()
  1471. << "Could not load " << *gtc->get_texture() << "\n";
  1472. return false;
  1473. }
  1474. }
  1475. gtc->enqueue_lru(&_prepared_objects->_graphics_memory_lru);
  1476. return true;
  1477. }
  1478. ////////////////////////////////////////////////////////////////////
  1479. // Function: TinyGraphicsStateGuardian::update_texture
  1480. // Access: Public
  1481. // Description: Ensures that the current Texture data is refreshed
  1482. // onto the GSG. This means updating the texture
  1483. // properties and/or re-uploading the texture image, if
  1484. // necessary. This should only be called within the
  1485. // draw thread.
  1486. //
  1487. // If force is true, this function will not return until
  1488. // the texture has been fully uploaded. If force is
  1489. // false, the function may choose to upload a simple
  1490. // version of the texture instead, if the texture is not
  1491. // fully resident (and if get_incomplete_render() is
  1492. // true).
  1493. ////////////////////////////////////////////////////////////////////
  1494. bool TinyGraphicsStateGuardian::
  1495. update_texture(TextureContext *tc, bool force, int stage_index) {
  1496. if (!update_texture(tc, force)) {
  1497. return false;
  1498. }
  1499. TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
  1500. GLTexture *gltex = &gtc->_gltex;
  1501. _c->current_textures[stage_index] = gltex;
  1502. ZTextureDef *texture_def = &_c->zb->current_textures[stage_index];
  1503. texture_def->levels = gltex->levels;
  1504. texture_def->s_max = gltex->s_max;
  1505. texture_def->t_max = gltex->t_max;
  1506. const V4 &bc = gltex->border_color;
  1507. int r = (int)(bc.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN)
  1508. + ZB_POINT_RED_MIN);
  1509. int g = (int)(bc.v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN)
  1510. + ZB_POINT_GREEN_MIN);
  1511. int b = (int)(bc.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN)
  1512. + ZB_POINT_BLUE_MIN);
  1513. int a = (int)(bc.v[3] * (ZB_POINT_ALPHA_MAX - ZB_POINT_ALPHA_MIN)
  1514. + ZB_POINT_ALPHA_MIN);
  1515. texture_def->border_color = RGBA_TO_PIXEL(r, g, b, a);
  1516. return true;
  1517. }
  1518. ////////////////////////////////////////////////////////////////////
  1519. // Function: TinyGraphicsStateGuardian::release_texture
  1520. // Access: Public, Virtual
  1521. // Description: Frees the GL resources previously allocated for the
  1522. // texture. This function should never be called
  1523. // directly; instead, call Texture::release() (or simply
  1524. // let the Texture destruct).
  1525. ////////////////////////////////////////////////////////////////////
  1526. void TinyGraphicsStateGuardian::
  1527. release_texture(TextureContext *tc) {
  1528. TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
  1529. _texturing_state = 0; // just in case
  1530. GLTexture *gltex = &gtc->_gltex;
  1531. if (gltex->allocated_buffer != NULL) {
  1532. nassertv(gltex->num_levels != 0);
  1533. TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
  1534. PANDA_FREE_ARRAY(gltex->allocated_buffer);
  1535. gltex->allocated_buffer = NULL;
  1536. gltex->total_bytecount = 0;
  1537. gltex->num_levels = 0;
  1538. } else {
  1539. nassertv(gltex->num_levels == 0);
  1540. }
  1541. gtc->dequeue_lru();
  1542. delete gtc;
  1543. }
  1544. ////////////////////////////////////////////////////////////////////
  1545. // Function: TinyGraphicsStateGuardian::do_issue_light
  1546. // Access: Protected, Virtual
  1547. // Description:
  1548. ////////////////////////////////////////////////////////////////////
  1549. void TinyGraphicsStateGuardian::
  1550. do_issue_light() {
  1551. // Initialize the current ambient light total and newly enabled
  1552. // light list
  1553. LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
  1554. int num_enabled = 0;
  1555. int num_on_lights = 0;
  1556. const LightAttrib *target_light = DCAST(LightAttrib, _target_rs->get_attrib_def(LightAttrib::get_class_slot()));
  1557. if (display_cat.is_spam()) {
  1558. display_cat.spam()
  1559. << "do_issue_light: " << target_light << "\n";
  1560. }
  1561. // First, release all of the previously-assigned lights.
  1562. clear_light_state();
  1563. // Now, assign new lights.
  1564. if (target_light != (LightAttrib *)NULL) {
  1565. CPT(LightAttrib) new_light = target_light->filter_to_max(_max_lights);
  1566. if (display_cat.is_spam()) {
  1567. new_light->write(display_cat.spam(false), 2);
  1568. }
  1569. num_on_lights = new_light->get_num_on_lights();
  1570. for (int li = 0; li < num_on_lights; li++) {
  1571. NodePath light = new_light->get_on_light(li);
  1572. nassertv(!light.is_empty());
  1573. Light *light_obj = light.node()->as_light();
  1574. nassertv(light_obj != (Light *)NULL);
  1575. _lighting_enabled = true;
  1576. _c->lighting_enabled = true;
  1577. if (light_obj->get_type() == AmbientLight::get_class_type()) {
  1578. // Accumulate all of the ambient lights together into one.
  1579. cur_ambient_light += light_obj->get_color();
  1580. } else {
  1581. // Other kinds of lights each get their own GLLight object.
  1582. light_obj->bind(this, light, num_enabled);
  1583. num_enabled++;
  1584. // Handle the diffuse color here, since all lights have this
  1585. // property.
  1586. GLLight *gl_light = _c->first_light;
  1587. nassertv(gl_light != NULL);
  1588. const LColor &diffuse = light_obj->get_color();
  1589. gl_light->diffuse.v[0] = diffuse[0];
  1590. gl_light->diffuse.v[1] = diffuse[1];
  1591. gl_light->diffuse.v[2] = diffuse[2];
  1592. gl_light->diffuse.v[3] = diffuse[3];
  1593. }
  1594. }
  1595. }
  1596. _c->ambient_light_model.v[0] = cur_ambient_light[0];
  1597. _c->ambient_light_model.v[1] = cur_ambient_light[1];
  1598. _c->ambient_light_model.v[2] = cur_ambient_light[2];
  1599. _c->ambient_light_model.v[3] = cur_ambient_light[3];
  1600. // Changing the lighting state means we need to reapply the
  1601. // transform in begin_draw_primitives().
  1602. _transform_stale = true;
  1603. }
  1604. ////////////////////////////////////////////////////////////////////
  1605. // Function: TinyGraphicsStateGuardian::bind_light
  1606. // Access: Public, Virtual
  1607. // Description: Called the first time a particular light has been
  1608. // bound to a given id within a frame, this should set
  1609. // up the associated hardware light with the light's
  1610. // properties.
  1611. ////////////////////////////////////////////////////////////////////
  1612. void TinyGraphicsStateGuardian::
  1613. bind_light(PointLight *light_obj, const NodePath &light, int light_id) {
  1614. pair<Lights::iterator, bool> lookup = _plights.insert(Lights::value_type(light, GLLight()));
  1615. GLLight *gl_light = &(*lookup.first).second;
  1616. if (lookup.second) {
  1617. // It's a brand new light. Define it.
  1618. memset(gl_light, 0, sizeof(GLLight));
  1619. const LColor &specular = light_obj->get_specular_color();
  1620. gl_light->specular.v[0] = specular[0];
  1621. gl_light->specular.v[1] = specular[1];
  1622. gl_light->specular.v[2] = specular[2];
  1623. gl_light->specular.v[3] = specular[3];
  1624. // Position needs to specify x, y, z, and w
  1625. // w == 1 implies non-infinite position
  1626. CPT(TransformState) render_transform =
  1627. _cs_transform->compose(_scene_setup->get_world_transform());
  1628. CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
  1629. CPT(TransformState) net_transform = render_transform->compose(transform);
  1630. LPoint3 pos = light_obj->get_point() * net_transform->get_mat();
  1631. gl_light->position.v[0] = pos[0];
  1632. gl_light->position.v[1] = pos[1];
  1633. gl_light->position.v[2] = pos[2];
  1634. gl_light->position.v[3] = 1.0f;
  1635. // Exponent == 0 implies uniform light distribution
  1636. gl_light->spot_exponent = 0.0f;
  1637. // Cutoff == 180 means uniform point light source
  1638. gl_light->spot_cutoff = 180.0f;
  1639. const LVecBase3 &att = light_obj->get_attenuation();
  1640. gl_light->attenuation[0] = att[0];
  1641. gl_light->attenuation[1] = att[1];
  1642. gl_light->attenuation[2] = att[2];
  1643. }
  1644. nassertv(gl_light->next == NULL);
  1645. // Add it to the linked list of active lights.
  1646. gl_light->next = _c->first_light;
  1647. _c->first_light = gl_light;
  1648. }
  1649. ////////////////////////////////////////////////////////////////////
  1650. // Function: TinyGraphicsStateGuardian::bind_light
  1651. // Access: Public, Virtual
  1652. // Description: Called the first time a particular light has been
  1653. // bound to a given id within a frame, this should set
  1654. // up the associated hardware light with the light's
  1655. // properties.
  1656. ////////////////////////////////////////////////////////////////////
  1657. void TinyGraphicsStateGuardian::
  1658. bind_light(DirectionalLight *light_obj, const NodePath &light, int light_id) {
  1659. pair<Lights::iterator, bool> lookup = _dlights.insert(Lights::value_type(light, GLLight()));
  1660. GLLight *gl_light = &(*lookup.first).second;
  1661. if (lookup.second) {
  1662. // It's a brand new light. Define it.
  1663. memset(gl_light, 0, sizeof(GLLight));
  1664. const LColor &specular = light_obj->get_specular_color();
  1665. gl_light->specular.v[0] = specular[0];
  1666. gl_light->specular.v[1] = specular[1];
  1667. gl_light->specular.v[2] = specular[2];
  1668. gl_light->specular.v[3] = specular[3];
  1669. // Position needs to specify x, y, z, and w
  1670. // w == 0 implies light is at infinity
  1671. CPT(TransformState) render_transform =
  1672. _cs_transform->compose(_scene_setup->get_world_transform());
  1673. CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
  1674. CPT(TransformState) net_transform = render_transform->compose(transform);
  1675. LVector3 dir = light_obj->get_direction() * net_transform->get_mat();
  1676. dir.normalize();
  1677. gl_light->position.v[0] = -dir[0];
  1678. gl_light->position.v[1] = -dir[1];
  1679. gl_light->position.v[2] = -dir[2];
  1680. gl_light->position.v[3] = 0.0f;
  1681. gl_light->norm_position.v[0] = -dir[0];
  1682. gl_light->norm_position.v[1] = -dir[1];
  1683. gl_light->norm_position.v[2] = -dir[2];
  1684. gl_V3_Norm(&gl_light->norm_position);
  1685. // Exponent == 0 implies uniform light distribution
  1686. gl_light->spot_exponent = 0.0f;
  1687. // Cutoff == 180 means uniform point light source
  1688. gl_light->spot_cutoff = 180.0f;
  1689. // Default attenuation values (only spotlight and point light can
  1690. // modify these)
  1691. gl_light->attenuation[0] = 1.0f;
  1692. gl_light->attenuation[1] = 0.0f;
  1693. gl_light->attenuation[2] = 0.0f;
  1694. }
  1695. nassertv(gl_light->next == NULL);
  1696. // Add it to the linked list of active lights.
  1697. gl_light->next = _c->first_light;
  1698. _c->first_light = gl_light;
  1699. }
  1700. ////////////////////////////////////////////////////////////////////
  1701. // Function: TinyGraphicsStateGuardian::bind_light
  1702. // Access: Public, Virtual
  1703. // Description: Called the first time a particular light has been
  1704. // bound to a given id within a frame, this should set
  1705. // up the associated hardware light with the light's
  1706. // properties.
  1707. ////////////////////////////////////////////////////////////////////
  1708. void TinyGraphicsStateGuardian::
  1709. bind_light(Spotlight *light_obj, const NodePath &light, int light_id) {
  1710. pair<Lights::iterator, bool> lookup = _plights.insert(Lights::value_type(light, GLLight()));
  1711. GLLight *gl_light = &(*lookup.first).second;
  1712. if (lookup.second) {
  1713. // It's a brand new light. Define it.
  1714. memset(gl_light, 0, sizeof(GLLight));
  1715. const LColor &specular = light_obj->get_specular_color();
  1716. gl_light->specular.v[0] = specular[0];
  1717. gl_light->specular.v[1] = specular[1];
  1718. gl_light->specular.v[2] = specular[2];
  1719. gl_light->specular.v[3] = specular[3];
  1720. Lens *lens = light_obj->get_lens();
  1721. nassertv(lens != (Lens *)NULL);
  1722. // Position needs to specify x, y, z, and w
  1723. // w == 1 implies non-infinite position
  1724. CPT(TransformState) render_transform =
  1725. _cs_transform->compose(_scene_setup->get_world_transform());
  1726. CPT(TransformState) transform = light.get_transform(_scene_setup->get_scene_root().get_parent());
  1727. CPT(TransformState) net_transform = render_transform->compose(transform);
  1728. const LMatrix4 &light_mat = net_transform->get_mat();
  1729. LPoint3 pos = lens->get_nodal_point() * light_mat;
  1730. LVector3 dir = lens->get_view_vector() * light_mat;
  1731. dir.normalize();
  1732. gl_light->position.v[0] = pos[0];
  1733. gl_light->position.v[1] = pos[1];
  1734. gl_light->position.v[2] = pos[2];
  1735. gl_light->position.v[3] = 1.0f;
  1736. gl_light->spot_direction.v[0] = dir[0];
  1737. gl_light->spot_direction.v[1] = dir[1];
  1738. gl_light->spot_direction.v[2] = dir[2];
  1739. gl_light->norm_spot_direction.v[0] = dir[0];
  1740. gl_light->norm_spot_direction.v[1] = dir[1];
  1741. gl_light->norm_spot_direction.v[2] = dir[2];
  1742. gl_V3_Norm(&gl_light->norm_spot_direction);
  1743. gl_light->spot_exponent = light_obj->get_exponent();
  1744. gl_light->spot_cutoff = lens->get_hfov() * 0.5f;
  1745. const LVecBase3 &att = light_obj->get_attenuation();
  1746. gl_light->attenuation[0] = att[0];
  1747. gl_light->attenuation[1] = att[1];
  1748. gl_light->attenuation[2] = att[2];
  1749. }
  1750. nassertv(gl_light->next == NULL);
  1751. // Add it to the linked list of active lights.
  1752. gl_light->next = _c->first_light;
  1753. _c->first_light = gl_light;
  1754. }
  1755. ////////////////////////////////////////////////////////////////////
  1756. // Function: TinyGraphicsStateGuardian::do_issue_transform
  1757. // Access: Protected
  1758. // Description: Sends the indicated transform matrix to the graphics
  1759. // API to be applied to future vertices.
  1760. //
  1761. // This transform is the internal_transform, already
  1762. // converted into the GSG's internal coordinate system.
  1763. ////////////////////////////////////////////////////////////////////
  1764. void TinyGraphicsStateGuardian::
  1765. do_issue_transform() {
  1766. _transform_state_pcollector.add_level(1);
  1767. _transform_stale = true;
  1768. if (_auto_rescale_normal) {
  1769. do_auto_rescale_normal();
  1770. }
  1771. }
  1772. ////////////////////////////////////////////////////////////////////
  1773. // Function: TinyGraphicsStateGuardian::do_issue_render_mode
  1774. // Access: Protected
  1775. // Description:
  1776. ////////////////////////////////////////////////////////////////////
  1777. void TinyGraphicsStateGuardian::
  1778. do_issue_render_mode() {
  1779. const RenderModeAttrib *target_render_mode = DCAST(RenderModeAttrib, _target_rs->get_attrib_def(RenderModeAttrib::get_class_slot()));
  1780. _filled_flat = false;
  1781. switch (target_render_mode->get_mode()) {
  1782. case RenderModeAttrib::M_unchanged:
  1783. case RenderModeAttrib::M_filled:
  1784. _c->draw_triangle_front = gl_draw_triangle_fill;
  1785. _c->draw_triangle_back = gl_draw_triangle_fill;
  1786. break;
  1787. case RenderModeAttrib::M_filled_flat:
  1788. _c->draw_triangle_front = gl_draw_triangle_fill;
  1789. _c->draw_triangle_back = gl_draw_triangle_fill;
  1790. _filled_flat = true;
  1791. break;
  1792. case RenderModeAttrib::M_wireframe:
  1793. _c->draw_triangle_front = gl_draw_triangle_line;
  1794. _c->draw_triangle_back = gl_draw_triangle_line;
  1795. break;
  1796. case RenderModeAttrib::M_point:
  1797. _c->draw_triangle_front = gl_draw_triangle_point;
  1798. _c->draw_triangle_back = gl_draw_triangle_point;
  1799. break;
  1800. default:
  1801. tinydisplay_cat.error()
  1802. << "Unknown render mode " << (int)target_render_mode->get_mode() << endl;
  1803. }
  1804. }
  1805. ////////////////////////////////////////////////////////////////////
  1806. // Function: TinyGraphicsStateGuardian::do_issue_rescale_normal
  1807. // Access: Protected
  1808. // Description:
  1809. ////////////////////////////////////////////////////////////////////
  1810. void TinyGraphicsStateGuardian::
  1811. do_issue_rescale_normal() {
  1812. const RescaleNormalAttrib *target_rescale_normal = DCAST(RescaleNormalAttrib, _target_rs->get_attrib_def(RescaleNormalAttrib::get_class_slot()));
  1813. RescaleNormalAttrib::Mode mode = target_rescale_normal->get_mode();
  1814. _auto_rescale_normal = false;
  1815. switch (mode) {
  1816. case RescaleNormalAttrib::M_none:
  1817. _c->normalize_enabled = false;
  1818. _c->normal_scale = 1.0f;
  1819. break;
  1820. case RescaleNormalAttrib::M_normalize:
  1821. _c->normalize_enabled = true;
  1822. _c->normal_scale = 1.0f;
  1823. break;
  1824. case RescaleNormalAttrib::M_rescale:
  1825. case RescaleNormalAttrib::M_auto:
  1826. _auto_rescale_normal = true;
  1827. do_auto_rescale_normal();
  1828. break;
  1829. default:
  1830. tinydisplay_cat.error()
  1831. << "Unknown rescale_normal mode " << (int)mode << endl;
  1832. }
  1833. }
  1834. ////////////////////////////////////////////////////////////////////
  1835. // Function: TinyGraphicsStateGuardian::do_issue_depth_offset
  1836. // Access: Protected
  1837. // Description:
  1838. ////////////////////////////////////////////////////////////////////
  1839. void TinyGraphicsStateGuardian::
  1840. do_issue_depth_offset() {
  1841. const DepthOffsetAttrib *target_depth_offset = DCAST(DepthOffsetAttrib, _target_rs->get_attrib_def(DepthOffsetAttrib::get_class_slot()));
  1842. int offset = target_depth_offset->get_offset();
  1843. _c->zbias = offset;
  1844. PN_stdfloat min_value = target_depth_offset->get_min_value();
  1845. PN_stdfloat max_value = target_depth_offset->get_max_value();
  1846. if (min_value == 0.0f && max_value == 1.0f) {
  1847. _c->has_zrange = false;
  1848. } else {
  1849. _c->has_zrange = true;
  1850. _c->zmin = min_value;
  1851. _c->zrange = max_value - min_value;
  1852. }
  1853. }
  1854. ////////////////////////////////////////////////////////////////////
  1855. // Function: TinyGraphicsStateGuardian::do_issue_cull_face
  1856. // Access: Protected
  1857. // Description:
  1858. ////////////////////////////////////////////////////////////////////
  1859. void TinyGraphicsStateGuardian::
  1860. do_issue_cull_face() {
  1861. const CullFaceAttrib *target_cull_face = DCAST(CullFaceAttrib, _target_rs->get_attrib_def(CullFaceAttrib::get_class_slot()));
  1862. CullFaceAttrib::Mode mode = target_cull_face->get_effective_mode();
  1863. switch (mode) {
  1864. case CullFaceAttrib::M_cull_none:
  1865. _c->cull_face_enabled = false;
  1866. break;
  1867. case CullFaceAttrib::M_cull_clockwise:
  1868. _c->cull_face_enabled = true;
  1869. _c->cull_clockwise = true;
  1870. break;
  1871. case CullFaceAttrib::M_cull_counter_clockwise:
  1872. _c->cull_face_enabled = true;
  1873. _c->cull_clockwise = false;
  1874. break;
  1875. default:
  1876. tinydisplay_cat.error()
  1877. << "invalid cull face mode " << (int)mode << endl;
  1878. break;
  1879. }
  1880. }
  1881. ////////////////////////////////////////////////////////////////////
  1882. // Function: TinyGraphicsStateGuardian::do_issue_material
  1883. // Access: Protected
  1884. // Description:
  1885. ////////////////////////////////////////////////////////////////////
  1886. void TinyGraphicsStateGuardian::
  1887. do_issue_material() {
  1888. static Material empty;
  1889. const MaterialAttrib *target_material = DCAST(MaterialAttrib, _target_rs->get_attrib_def(MaterialAttrib::get_class_slot()));
  1890. const Material *material;
  1891. if (target_material == (MaterialAttrib *)NULL ||
  1892. target_material->is_off()) {
  1893. material = &empty;
  1894. } else {
  1895. material = target_material->get_material();
  1896. }
  1897. // Apply the material parameters to the front face.
  1898. setup_material(&_c->materials[0], material);
  1899. if (material->get_twoside()) {
  1900. // Also apply the material parameters to the back face.
  1901. setup_material(&_c->materials[1], material);
  1902. }
  1903. _c->local_light_model = material->get_local();
  1904. _c->light_model_two_side = material->get_twoside();
  1905. }
  1906. ////////////////////////////////////////////////////////////////////
  1907. // Function: TinyGraphicsStateGuardian::do_issue_texture
  1908. // Access: Protected
  1909. // Description:
  1910. ////////////////////////////////////////////////////////////////////
  1911. void TinyGraphicsStateGuardian::
  1912. do_issue_texture() {
  1913. _texturing_state = 0; // untextured
  1914. _c->num_textures_enabled = 0;
  1915. int num_stages = _target_texture->get_num_on_ff_stages();
  1916. if (num_stages == 0) {
  1917. // No texturing.
  1918. return;
  1919. }
  1920. nassertv(num_stages <= MAX_TEXTURE_STAGES);
  1921. bool all_replace = true;
  1922. bool all_nearest = true;
  1923. bool all_mipmap_nearest = true;
  1924. bool any_mipmap = false;
  1925. bool needs_general = false;
  1926. Texture::QualityLevel best_quality_level = Texture::QL_default;
  1927. for (int si = 0; si < num_stages; ++si) {
  1928. TextureStage *stage = _target_texture->get_on_ff_stage(si);
  1929. Texture *texture = _target_texture->get_on_texture(stage);
  1930. nassertv(texture != (Texture *)NULL);
  1931. int view = get_current_tex_view_offset() + stage->get_tex_view_offset();
  1932. TextureContext *tc = texture->prepare_now(view, _prepared_objects, this);
  1933. if (tc == (TextureContext *)NULL) {
  1934. // Something wrong with this texture; skip it.
  1935. return;
  1936. }
  1937. // Then, turn on the current texture mode.
  1938. if (!update_texture(tc, false, si)) {
  1939. return;
  1940. }
  1941. // M_replace means M_replace; anything else is treated the same as
  1942. // M_modulate.
  1943. if (stage->get_mode() != TextureStage::M_replace) {
  1944. all_replace = false;
  1945. }
  1946. Texture::QualityLevel quality_level = _texture_quality_override;
  1947. if (quality_level == Texture::QL_default) {
  1948. quality_level = texture->get_quality_level();
  1949. }
  1950. if (quality_level == Texture::QL_default) {
  1951. quality_level = texture_quality_level;
  1952. }
  1953. best_quality_level = max(best_quality_level, quality_level);
  1954. ZTextureDef *texture_def = &_c->zb->current_textures[si];
  1955. // Fill in the filter func pointers. These may not actually get
  1956. // called, if we decide below we can inline the filters.
  1957. Texture::FilterType minfilter = texture->get_minfilter();
  1958. Texture::FilterType magfilter = texture->get_magfilter();
  1959. if (td_ignore_mipmaps && Texture::is_mipmap(minfilter)) {
  1960. // Downgrade mipmaps.
  1961. if (minfilter == Texture::FT_nearest_mipmap_nearest) {
  1962. minfilter = Texture::FT_nearest;
  1963. } else {
  1964. minfilter = Texture::FT_linear;
  1965. }
  1966. }
  1967. // Depending on this particular texture's quality level, we may
  1968. // downgrade the requested filters.
  1969. if (quality_level == Texture::QL_fastest) {
  1970. minfilter = Texture::FT_nearest;
  1971. magfilter = Texture::FT_nearest;
  1972. } else if (quality_level == Texture::QL_normal) {
  1973. if (Texture::is_mipmap(minfilter)) {
  1974. minfilter = Texture::FT_nearest_mipmap_nearest;
  1975. } else {
  1976. minfilter = Texture::FT_nearest;
  1977. }
  1978. magfilter = Texture::FT_nearest;
  1979. } else if (quality_level == Texture::QL_best) {
  1980. minfilter = texture->get_effective_minfilter();
  1981. magfilter = texture->get_effective_magfilter();
  1982. }
  1983. texture_def->tex_minfilter_func = get_tex_filter_func(minfilter);
  1984. texture_def->tex_magfilter_func = get_tex_filter_func(magfilter);
  1985. Texture::WrapMode wrap_u = texture->get_wrap_u();
  1986. Texture::WrapMode wrap_v = texture->get_wrap_v();
  1987. if (td_ignore_clamp) {
  1988. wrap_u = Texture::WM_repeat;
  1989. wrap_v = Texture::WM_repeat;
  1990. }
  1991. if (wrap_u != Texture::WM_repeat || wrap_v != Texture::WM_repeat) {
  1992. // We have some nonstandard wrap mode. This will force the use
  1993. // of the general texfilter mode.
  1994. needs_general = true;
  1995. // We need another level of indirection to implement the
  1996. // different texcoord wrap modes. This means we will be using
  1997. // the _impl function pointers, which are called by the toplevel
  1998. // function.
  1999. texture_def->tex_minfilter_func_impl = texture_def->tex_minfilter_func;
  2000. texture_def->tex_magfilter_func_impl = texture_def->tex_magfilter_func;
  2001. // Now assign the toplevel function pointer to do the
  2002. // appropriate texture coordinate wrapping/clamping.
  2003. texture_def->tex_minfilter_func = apply_wrap_general_minfilter;
  2004. texture_def->tex_magfilter_func = apply_wrap_general_magfilter;
  2005. texture_def->tex_wrap_u_func = get_tex_wrap_func(wrap_u);
  2006. texture_def->tex_wrap_v_func = get_tex_wrap_func(wrap_v);
  2007. // The following special cases are handled inline, rather than
  2008. // relying on the above wrap function pointers.
  2009. if (wrap_u && Texture::WM_border_color && wrap_v == Texture::WM_border_color) {
  2010. texture_def->tex_minfilter_func = apply_wrap_border_color_minfilter;
  2011. texture_def->tex_magfilter_func = apply_wrap_border_color_magfilter;
  2012. } else if (wrap_u && Texture::WM_clamp && wrap_v == Texture::WM_clamp) {
  2013. texture_def->tex_minfilter_func = apply_wrap_clamp_minfilter;
  2014. texture_def->tex_magfilter_func = apply_wrap_clamp_magfilter;
  2015. }
  2016. }
  2017. if (minfilter != Texture::FT_nearest || magfilter != Texture::FT_nearest) {
  2018. all_nearest = false;
  2019. }
  2020. if (minfilter != Texture::FT_nearest_mipmap_nearest ||
  2021. magfilter != Texture::FT_nearest) {
  2022. all_mipmap_nearest = false;
  2023. }
  2024. if (Texture::is_mipmap(minfilter)) {
  2025. any_mipmap = true;
  2026. }
  2027. }
  2028. // Set a few state cache values.
  2029. _c->num_textures_enabled = num_stages;
  2030. _texture_replace = all_replace;
  2031. _texturing_state = 2; // perspective (perspective-correct texturing)
  2032. if (num_stages >= 3) {
  2033. _texturing_state = 4; // multitex3
  2034. } else if (num_stages == 2) {
  2035. _texturing_state = 3; // multitex2
  2036. } else if (!td_perspective_textures) {
  2037. _texturing_state = 1; // textured (not perspective correct)
  2038. }
  2039. if (best_quality_level == Texture::QL_best) {
  2040. // This is the most generic texture filter. Slow, but pretty.
  2041. _texfilter_state = 2; // tgeneral
  2042. if (!needs_general) {
  2043. if (all_nearest) {
  2044. // This case is inlined.
  2045. _texfilter_state = 0; // tnearest
  2046. } else if (all_mipmap_nearest) {
  2047. // So is this case.
  2048. _texfilter_state = 1; // tmipmap
  2049. }
  2050. }
  2051. } else if (best_quality_level == Texture::QL_fastest) {
  2052. // This is the cheapest texture filter. We disallow mipmaps and
  2053. // perspective correctness.
  2054. _texfilter_state = 0; // tnearest
  2055. _texturing_state = 1; // textured (not perspective correct, no multitexture)
  2056. } else {
  2057. // This is the default texture filter. We use nearest sampling if
  2058. // there are no mipmaps, and mipmap_nearest if there are any
  2059. // mipmaps--these are the two inlined filters.
  2060. _texfilter_state = 0; // tnearest
  2061. if (any_mipmap) {
  2062. _texfilter_state = 1; // tmipmap
  2063. }
  2064. if (needs_general) {
  2065. // To support nonstandard texcoord wrapping etc, we need to
  2066. // force the general texfilter mode.
  2067. _texfilter_state = 2; // tgeneral
  2068. }
  2069. }
  2070. }
  2071. ////////////////////////////////////////////////////////////////////
  2072. // Function: TinyGraphicsStateGuardian::do_issue_scissor
  2073. // Access: Protected
  2074. // Description:
  2075. ////////////////////////////////////////////////////////////////////
  2076. void TinyGraphicsStateGuardian::
  2077. do_issue_scissor() {
  2078. const ScissorAttrib *target_scissor = DCAST(ScissorAttrib, _target_rs->get_attrib_def(ScissorAttrib::get_class_slot()));
  2079. const LVecBase4 &frame = target_scissor->get_frame();
  2080. set_scissor(frame[0], frame[1], frame[2], frame[3]);
  2081. }
  2082. ////////////////////////////////////////////////////////////////////
  2083. // Function: TinyGraphicsStateGuardian::set_scissor
  2084. // Access: Private
  2085. // Description: Sets up the scissor region, as a set of coordinates
  2086. // relative to the current viewport.
  2087. ////////////////////////////////////////////////////////////////////
  2088. void TinyGraphicsStateGuardian::
  2089. set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
  2090. _c->scissor.left = left;
  2091. _c->scissor.right = right;
  2092. _c->scissor.bottom = bottom;
  2093. _c->scissor.top = top;
  2094. gl_eval_viewport(_c);
  2095. PN_stdfloat xsize = right - left;
  2096. PN_stdfloat ysize = top - bottom;
  2097. PN_stdfloat xcenter = (left + right) - 1.0f;
  2098. PN_stdfloat ycenter = (bottom + top) - 1.0f;
  2099. if (xsize == 0.0f || ysize == 0.0f) {
  2100. // If the scissor region is zero, nothing will be drawn anyway, so
  2101. // don't worry about it.
  2102. _scissor_mat = TransformState::make_identity();
  2103. } else {
  2104. _scissor_mat = TransformState::make_scale(LVecBase3(1.0f / xsize, 1.0f / ysize, 1.0f))->compose(TransformState::make_pos(LPoint3(-xcenter, -ycenter, 0.0f)));
  2105. }
  2106. }
  2107. ////////////////////////////////////////////////////////////////////
  2108. // Function: TinyGraphicsStateGuardian::apply_texture
  2109. // Access: Protected
  2110. // Description: Updates the graphics state with the current
  2111. // information for this texture, and makes it the
  2112. // current texture available for rendering.
  2113. ////////////////////////////////////////////////////////////////////
  2114. bool TinyGraphicsStateGuardian::
  2115. apply_texture(TextureContext *tc) {
  2116. TinyTextureContext *gtc = DCAST(TinyTextureContext, tc);
  2117. gtc->set_active(true);
  2118. return true;
  2119. }
  2120. ////////////////////////////////////////////////////////////////////
  2121. // Function: TinyGraphicsStateGuardian::upload_texture
  2122. // Access: Protected
  2123. // Description: Uploads the texture image to the graphics state.
  2124. //
  2125. // The return value is true if successful, or false if
  2126. // the texture has no image.
  2127. ////////////////////////////////////////////////////////////////////
  2128. bool TinyGraphicsStateGuardian::
  2129. upload_texture(TinyTextureContext *gtc, bool force) {
  2130. Texture *tex = gtc->get_texture();
  2131. if (_effective_incomplete_render && !force) {
  2132. if (!tex->has_ram_image() && tex->might_have_ram_image() &&
  2133. tex->has_simple_ram_image() &&
  2134. !_loader.is_null()) {
  2135. // If we don't have the texture data right now, go get it, but in
  2136. // the meantime load a temporary simple image in its place.
  2137. async_reload_texture(gtc);
  2138. if (!tex->has_ram_image()) {
  2139. if (gtc->was_simple_image_modified()) {
  2140. return upload_simple_texture(gtc);
  2141. }
  2142. return true;
  2143. }
  2144. }
  2145. }
  2146. PStatTimer timer(_load_texture_pcollector);
  2147. CPTA_uchar src_image = tex->get_uncompressed_ram_image();
  2148. if (src_image.is_null()) {
  2149. return false;
  2150. }
  2151. if (tinydisplay_cat.is_debug()) {
  2152. tinydisplay_cat.debug()
  2153. << "loading texture " << tex->get_name() << "\n";
  2154. }
  2155. #ifdef DO_PSTATS
  2156. _data_transferred_pcollector.add_level(tex->get_ram_image_size());
  2157. #endif
  2158. GLTexture *gltex = &gtc->_gltex;
  2159. int num_levels = 1;
  2160. if (tex->uses_mipmaps()) {
  2161. if (!tex->has_all_ram_mipmap_images()) {
  2162. tex->generate_ram_mipmap_images();
  2163. }
  2164. num_levels = tex->get_num_ram_mipmap_images();
  2165. }
  2166. if (!setup_gltex(gltex, tex->get_x_size(), tex->get_y_size(), num_levels)) {
  2167. return false;
  2168. }
  2169. LColor border_color = tex->get_border_color();
  2170. gltex->border_color.v[0] = border_color[0];
  2171. gltex->border_color.v[1] = border_color[1];
  2172. gltex->border_color.v[2] = border_color[2];
  2173. gltex->border_color.v[3] = border_color[3];
  2174. int bytecount = 0;
  2175. int xsize = gltex->xsize;
  2176. int ysize = gltex->ysize;
  2177. for (int level = 0; level < gltex->num_levels; ++level) {
  2178. ZTextureLevel *dest = &gltex->levels[level];
  2179. switch (tex->get_format()) {
  2180. case Texture::F_rgb:
  2181. case Texture::F_rgb5:
  2182. case Texture::F_rgb8:
  2183. case Texture::F_rgb12:
  2184. case Texture::F_rgb332:
  2185. copy_rgb_image(dest, xsize, ysize, gtc, level);
  2186. break;
  2187. case Texture::F_rgba:
  2188. case Texture::F_rgbm:
  2189. case Texture::F_rgba4:
  2190. case Texture::F_rgba5:
  2191. case Texture::F_rgba8:
  2192. case Texture::F_rgba12:
  2193. case Texture::F_rgba16:
  2194. case Texture::F_rgba32:
  2195. copy_rgba_image(dest, xsize, ysize, gtc, level);
  2196. break;
  2197. case Texture::F_luminance:
  2198. copy_lum_image(dest, xsize, ysize, gtc, level);
  2199. break;
  2200. case Texture::F_red:
  2201. copy_one_channel_image(dest, xsize, ysize, gtc, level, 0);
  2202. break;
  2203. case Texture::F_green:
  2204. copy_one_channel_image(dest, xsize, ysize, gtc, level, 1);
  2205. break;
  2206. case Texture::F_blue:
  2207. copy_one_channel_image(dest, xsize, ysize, gtc, level, 2);
  2208. break;
  2209. case Texture::F_alpha:
  2210. copy_alpha_image(dest, xsize, ysize, gtc, level);
  2211. break;
  2212. case Texture::F_luminance_alphamask:
  2213. case Texture::F_luminance_alpha:
  2214. copy_la_image(dest, xsize, ysize, gtc, level);
  2215. break;
  2216. }
  2217. bytecount += xsize * ysize * 4;
  2218. xsize = max(xsize >> 1, 1);
  2219. ysize = max(ysize >> 1, 1);
  2220. }
  2221. gtc->update_data_size_bytes(bytecount);
  2222. get_engine()->texture_uploaded(tex);
  2223. gtc->mark_loaded();
  2224. return true;
  2225. }
  2226. ////////////////////////////////////////////////////////////////////
  2227. // Function: TinyGraphicsStateGuardian::upload_simple_texture
  2228. // Access: Protected
  2229. // Description: This is used as a standin for upload_texture
  2230. // when the texture in question is unavailable (e.g. it
  2231. // hasn't yet been loaded from disk). Until the texture
  2232. // image itself becomes available, we will render the
  2233. // texture's "simple" image--a sharply reduced version
  2234. // of the same texture.
  2235. ////////////////////////////////////////////////////////////////////
  2236. bool TinyGraphicsStateGuardian::
  2237. upload_simple_texture(TinyTextureContext *gtc) {
  2238. PStatTimer timer(_load_texture_pcollector);
  2239. Texture *tex = gtc->get_texture();
  2240. nassertr(tex != (Texture *)NULL, false);
  2241. const unsigned char *image_ptr = tex->get_simple_ram_image();
  2242. if (image_ptr == (const unsigned char *)NULL) {
  2243. return false;
  2244. }
  2245. size_t image_size = tex->get_simple_ram_image_size();
  2246. int width = tex->get_simple_x_size();
  2247. int height = tex->get_simple_y_size();
  2248. #ifdef DO_PSTATS
  2249. _data_transferred_pcollector.add_level(image_size);
  2250. #endif
  2251. GLTexture *gltex = &gtc->_gltex;
  2252. if (tinydisplay_cat.is_debug()) {
  2253. tinydisplay_cat.debug()
  2254. << "loading simple image for " << tex->get_name() << "\n";
  2255. }
  2256. if (!setup_gltex(gltex, width, height, 1)) {
  2257. return false;
  2258. }
  2259. LColor border_color = tex->get_border_color();
  2260. gltex->border_color.v[0] = border_color[0];
  2261. gltex->border_color.v[1] = border_color[1];
  2262. gltex->border_color.v[2] = border_color[2];
  2263. gltex->border_color.v[3] = border_color[3];
  2264. ZTextureLevel *dest = &gltex->levels[0];
  2265. memcpy(dest->pixmap, image_ptr, image_size);
  2266. gtc->mark_simple_loaded();
  2267. return true;
  2268. }
  2269. ////////////////////////////////////////////////////////////////////
  2270. // Function: TinyGraphicsStateGuardian::setup_gltex
  2271. // Access: Private
  2272. // Description: Sets the GLTexture size, bits, and masks
  2273. // appropriately, and allocates space for a pixmap.
  2274. // Does not fill the pixmap contents. Returns true if
  2275. // the texture is a valid size, false otherwise.
  2276. ////////////////////////////////////////////////////////////////////
  2277. bool TinyGraphicsStateGuardian::
  2278. setup_gltex(GLTexture *gltex, int x_size, int y_size, int num_levels) {
  2279. int s_bits = get_tex_shift(x_size);
  2280. int t_bits = get_tex_shift(y_size);
  2281. if (s_bits < 0 || t_bits < 0) {
  2282. return false;
  2283. }
  2284. num_levels = min(num_levels, MAX_MIPMAP_LEVELS);
  2285. gltex->xsize = x_size;
  2286. gltex->ysize = y_size;
  2287. gltex->s_max = 1 << (s_bits + ZB_POINT_ST_FRAC_BITS);
  2288. gltex->t_max = 1 << (t_bits + ZB_POINT_ST_FRAC_BITS);
  2289. gltex->num_levels = num_levels;
  2290. // We allocate one big buffer, large enough to include all the
  2291. // mipmap levels, and index into that buffer for each level. This
  2292. // cuts down on the number of individual alloc calls we have to make
  2293. // for each texture.
  2294. int total_bytecount = 0;
  2295. // Count up the total bytes required for all mipmap levels.
  2296. {
  2297. int x = x_size;
  2298. int y = y_size;
  2299. for (int level = 0; level < num_levels; ++level) {
  2300. int bytecount = x * y * 4;
  2301. total_bytecount += bytecount;
  2302. x = max((x >> 1), 1);
  2303. y = max((y >> 1), 1);
  2304. }
  2305. }
  2306. if (gltex->total_bytecount != total_bytecount) {
  2307. if (gltex->allocated_buffer != NULL) {
  2308. PANDA_FREE_ARRAY(gltex->allocated_buffer);
  2309. TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
  2310. }
  2311. gltex->allocated_buffer = PANDA_MALLOC_ARRAY(total_bytecount);
  2312. gltex->total_bytecount = total_bytecount;
  2313. TinyTextureContext::get_class_type().inc_memory_usage(TypeHandle::MC_array, total_bytecount);
  2314. }
  2315. char *next_buffer = (char *)gltex->allocated_buffer;
  2316. char *end_of_buffer = next_buffer + total_bytecount;
  2317. int level = 0;
  2318. ZTextureLevel *dest = NULL;
  2319. while (level < num_levels) {
  2320. dest = &gltex->levels[level];
  2321. int bytecount = x_size * y_size * 4;
  2322. dest->pixmap = (PIXEL *)next_buffer;
  2323. next_buffer += bytecount;
  2324. nassertr(next_buffer <= end_of_buffer, false);
  2325. dest->s_mask = ((1 << (s_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
  2326. dest->t_mask = ((1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
  2327. dest->s_shift = (ZB_POINT_ST_FRAC_BITS + level);
  2328. dest->t_shift = (ZB_POINT_ST_FRAC_BITS - s_bits + level);
  2329. x_size = max((x_size >> 1), 1);
  2330. y_size = max((y_size >> 1), 1);
  2331. s_bits = max(s_bits - 1, 0);
  2332. t_bits = max(t_bits - 1, 0);
  2333. ++level;
  2334. }
  2335. // Fill out the remaining mipmap arrays with copies of the last
  2336. // level, so we don't have to be concerned with running off the end
  2337. // of this array while scanning out triangles.
  2338. while (level < MAX_MIPMAP_LEVELS) {
  2339. gltex->levels[level] = *dest;
  2340. ++level;
  2341. }
  2342. return true;
  2343. }
  2344. ////////////////////////////////////////////////////////////////////
  2345. // Function: TinyGraphicsStateGuardian::get_tex_shift
  2346. // Access: Private
  2347. // Description: Calculates the bit shift count, such that (1 << shift)
  2348. // == size. Returns -1 if the size is not a power of 2
  2349. // or is larger than our largest allowable size.
  2350. ////////////////////////////////////////////////////////////////////
  2351. int TinyGraphicsStateGuardian::
  2352. get_tex_shift(int orig_size) {
  2353. if ((orig_size & (orig_size - 1)) != 0) {
  2354. // Not a power of 2.
  2355. return -1;
  2356. }
  2357. if (orig_size > _max_texture_dimension) {
  2358. return -1;
  2359. }
  2360. return count_bits_in_word((unsigned int)orig_size - 1);
  2361. }
  2362. ////////////////////////////////////////////////////////////////////
  2363. // Function: TinyGraphicsStateGuardian::copy_lum_image
  2364. // Access: Private, Static
  2365. // Description: Copies and scales the one-channel luminance image
  2366. // from the texture into the indicated ZTexture pixmap.
  2367. ////////////////////////////////////////////////////////////////////
  2368. void TinyGraphicsStateGuardian::
  2369. copy_lum_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
  2370. Texture *tex = gtc->get_texture();
  2371. nassertv(tex->get_num_components() == 1);
  2372. nassertv(tex->get_expected_mipmap_x_size(level) == xsize &&
  2373. tex->get_expected_mipmap_y_size(level) == ysize);
  2374. CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
  2375. nassertv(!src_image.is_null());
  2376. const unsigned char *src = src_image.p();
  2377. size_t view_size = tex->get_ram_mipmap_view_size(level);
  2378. src += view_size * gtc->get_view();
  2379. // Component width, and offset to the high-order byte.
  2380. int cw = tex->get_component_width();
  2381. #ifdef WORDS_BIGENDIAN
  2382. // Big-endian: the high-order byte is always first.
  2383. static const int co = 0;
  2384. #else
  2385. // Little-endian: the high-order byte is last.
  2386. int co = cw - 1;
  2387. #endif
  2388. unsigned int *dpix = (unsigned int *)dest->pixmap;
  2389. nassertv(dpix != NULL);
  2390. const unsigned char *spix = src;
  2391. int pixel_count = xsize * ysize;
  2392. while (pixel_count-- > 0) {
  2393. *dpix = RGBA8_TO_PIXEL(spix[co], spix[co], spix[co], 0xff);
  2394. ++dpix;
  2395. spix += cw;
  2396. }
  2397. }
  2398. ////////////////////////////////////////////////////////////////////
  2399. // Function: TinyGraphicsStateGuardian::copy_alpha_image
  2400. // Access: Private, Static
  2401. // Description: Copies and scales the one-channel alpha image
  2402. // from the texture into the indicated ZTexture pixmap.
  2403. ////////////////////////////////////////////////////////////////////
  2404. void TinyGraphicsStateGuardian::
  2405. copy_alpha_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
  2406. Texture *tex = gtc->get_texture();
  2407. nassertv(tex->get_num_components() == 1);
  2408. CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
  2409. nassertv(!src_image.is_null());
  2410. const unsigned char *src = src_image.p();
  2411. size_t view_size = tex->get_ram_mipmap_view_size(level);
  2412. src += view_size * gtc->get_view();
  2413. // Component width, and offset to the high-order byte.
  2414. int cw = tex->get_component_width();
  2415. #ifdef WORDS_BIGENDIAN
  2416. // Big-endian: the high-order byte is always first.
  2417. static const int co = 0;
  2418. #else
  2419. // Little-endian: the high-order byte is last.
  2420. int co = cw - 1;
  2421. #endif
  2422. unsigned int *dpix = (unsigned int *)dest->pixmap;
  2423. nassertv(dpix != NULL);
  2424. const unsigned char *spix = src;
  2425. int pixel_count = xsize * ysize;
  2426. while (pixel_count-- > 0) {
  2427. *dpix = RGBA8_TO_PIXEL(0xff, 0xff, 0xff, spix[co]);
  2428. ++dpix;
  2429. spix += cw;
  2430. }
  2431. }
  2432. ////////////////////////////////////////////////////////////////////
  2433. // Function: TinyGraphicsStateGuardian::copy_one_channel_image
  2434. // Access: Private, Static
  2435. // Description: Copies and scales the one-channel image (with a
  2436. // single channel, e.g. red, green, or blue) from
  2437. // the texture into the indicated ZTexture pixmap.
  2438. ////////////////////////////////////////////////////////////////////
  2439. void TinyGraphicsStateGuardian::
  2440. copy_one_channel_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level, int channel) {
  2441. Texture *tex = gtc->get_texture();
  2442. nassertv(tex->get_num_components() == 1);
  2443. CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
  2444. nassertv(!src_image.is_null());
  2445. const unsigned char *src = src_image.p();
  2446. size_t view_size = tex->get_ram_mipmap_view_size(level);
  2447. src += view_size * gtc->get_view();
  2448. // Component width, and offset to the high-order byte.
  2449. int cw = tex->get_component_width();
  2450. #ifdef WORDS_BIGENDIAN
  2451. // Big-endian: the high-order byte is always first.
  2452. static const int co = 0;
  2453. #else
  2454. // Little-endian: the high-order byte is last.
  2455. int co = cw - 1;
  2456. #endif
  2457. unsigned int *dpix = (unsigned int *)dest->pixmap;
  2458. nassertv(dpix != NULL);
  2459. const unsigned char *spix = src;
  2460. int pixel_count = xsize * ysize;
  2461. switch (channel) {
  2462. case 0:
  2463. while (pixel_count-- > 0) {
  2464. *dpix = RGBA8_TO_PIXEL(spix[co], 0, 0, 0xff);
  2465. ++dpix;
  2466. spix += cw;
  2467. }
  2468. break;
  2469. case 1:
  2470. while (pixel_count-- > 0) {
  2471. *dpix = RGBA8_TO_PIXEL(0, spix[co], 0, 0xff);
  2472. ++dpix;
  2473. spix += cw;
  2474. }
  2475. break;
  2476. case 2:
  2477. while (pixel_count-- > 0) {
  2478. *dpix = RGBA8_TO_PIXEL(0, 0, spix[co], 0xff);
  2479. ++dpix;
  2480. spix += cw;
  2481. }
  2482. break;
  2483. case 3:
  2484. while (pixel_count-- > 0) {
  2485. *dpix = RGBA8_TO_PIXEL(0, 0, 0, spix[co]);
  2486. ++dpix;
  2487. spix += cw;
  2488. }
  2489. break;
  2490. }
  2491. }
  2492. ////////////////////////////////////////////////////////////////////
  2493. // Function: TinyGraphicsStateGuardian::copy_la_image
  2494. // Access: Private, Static
  2495. // Description: Copies and scales the two-channel luminance-alpha
  2496. // image from the texture into the indicated ZTexture
  2497. // pixmap.
  2498. ////////////////////////////////////////////////////////////////////
  2499. void TinyGraphicsStateGuardian::
  2500. copy_la_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
  2501. Texture *tex = gtc->get_texture();
  2502. nassertv(tex->get_num_components() == 2);
  2503. CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
  2504. nassertv(!src_image.is_null());
  2505. const unsigned char *src = src_image.p();
  2506. size_t view_size = tex->get_ram_mipmap_view_size(level);
  2507. src += view_size * gtc->get_view();
  2508. // Component width, and offset to the high-order byte.
  2509. int cw = tex->get_component_width();
  2510. #ifdef WORDS_BIGENDIAN
  2511. // Big-endian: the high-order byte is always first.
  2512. static const int co = 0;
  2513. #else
  2514. // Little-endian: the high-order byte is last.
  2515. int co = cw - 1;
  2516. #endif
  2517. unsigned int *dpix = (unsigned int *)dest->pixmap;
  2518. nassertv(dpix != NULL);
  2519. const unsigned char *spix = src;
  2520. int pixel_count = xsize * ysize;
  2521. int inc = 2 * cw;
  2522. while (pixel_count-- > 0) {
  2523. *dpix = RGBA8_TO_PIXEL(spix[co], spix[co], spix[co], spix[cw + co]);
  2524. ++dpix;
  2525. spix += inc;
  2526. }
  2527. }
  2528. ////////////////////////////////////////////////////////////////////
  2529. // Function: TinyGraphicsStateGuardian::copy_rgb_image
  2530. // Access: Private, Static
  2531. // Description: Copies and scales the three-channel RGB image from
  2532. // the texture into the indicated ZTexture pixmap.
  2533. ////////////////////////////////////////////////////////////////////
  2534. void TinyGraphicsStateGuardian::
  2535. copy_rgb_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
  2536. Texture *tex = gtc->get_texture();
  2537. nassertv(tex->get_num_components() == 3);
  2538. CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
  2539. nassertv(!src_image.is_null());
  2540. const unsigned char *src = src_image.p();
  2541. size_t view_size = tex->get_ram_mipmap_view_size(level);
  2542. src += view_size * gtc->get_view();
  2543. // Component width, and offset to the high-order byte.
  2544. int cw = tex->get_component_width();
  2545. #ifdef WORDS_BIGENDIAN
  2546. // Big-endian: the high-order byte is always first.
  2547. static const int co = 0;
  2548. #else
  2549. // Little-endian: the high-order byte is last.
  2550. int co = cw - 1;
  2551. #endif
  2552. unsigned int *dpix = (unsigned int *)dest->pixmap;
  2553. nassertv(dpix != NULL);
  2554. const unsigned char *spix = src;
  2555. int pixel_count = xsize * ysize;
  2556. int inc = 3 * cw;
  2557. while (pixel_count-- > 0) {
  2558. *dpix = RGBA8_TO_PIXEL(spix[cw + cw + co], spix[cw + co], spix[co], 0xff);
  2559. ++dpix;
  2560. spix += inc;
  2561. }
  2562. }
  2563. ////////////////////////////////////////////////////////////////////
  2564. // Function: TinyGraphicsStateGuardian::copy_rgba_image
  2565. // Access: Private, Static
  2566. // Description: Copies and scales the four-channel RGBA image from
  2567. // the texture into the indicated ZTexture pixmap.
  2568. ////////////////////////////////////////////////////////////////////
  2569. void TinyGraphicsStateGuardian::
  2570. copy_rgba_image(ZTextureLevel *dest, int xsize, int ysize, TinyTextureContext *gtc, int level) {
  2571. Texture *tex = gtc->get_texture();
  2572. nassertv(tex->get_num_components() == 4);
  2573. CPTA_uchar src_image = tex->get_ram_mipmap_image(level);
  2574. nassertv(!src_image.is_null());
  2575. const unsigned char *src = src_image.p();
  2576. size_t view_size = tex->get_ram_mipmap_view_size(level);
  2577. src += view_size * gtc->get_view();
  2578. // Component width, and offset to the high-order byte.
  2579. int cw = tex->get_component_width();
  2580. #ifdef WORDS_BIGENDIAN
  2581. // Big-endian: the high-order byte is always first.
  2582. static const int co = 0;
  2583. #else
  2584. // Little-endian: the high-order byte is last.
  2585. int co = cw - 1;
  2586. #endif
  2587. unsigned int *dpix = (unsigned int *)dest->pixmap;
  2588. nassertv(dpix != NULL);
  2589. const unsigned char *spix = src;
  2590. int pixel_count = xsize * ysize;
  2591. int inc = 4 * cw;
  2592. while (pixel_count-- > 0) {
  2593. *dpix = RGBA8_TO_PIXEL(spix[cw + cw + co], spix[cw + co], spix[co], spix[cw + cw + cw + co]);
  2594. ++dpix;
  2595. spix += inc;
  2596. }
  2597. }
  2598. ////////////////////////////////////////////////////////////////////
  2599. // Function: TinyGraphicsStateGuardian::setup_material
  2600. // Access: Private
  2601. // Description: Applies the desired parametesr to the indicated
  2602. // GLMaterial object.
  2603. ////////////////////////////////////////////////////////////////////
  2604. void TinyGraphicsStateGuardian::
  2605. setup_material(GLMaterial *gl_material, const Material *material) {
  2606. const LColor &specular = material->get_specular();
  2607. gl_material->specular.v[0] = specular[0];
  2608. gl_material->specular.v[1] = specular[1];
  2609. gl_material->specular.v[2] = specular[2];
  2610. gl_material->specular.v[3] = specular[3];
  2611. const LColor &emission = material->get_emission();
  2612. gl_material->emission.v[0] = emission[0];
  2613. gl_material->emission.v[1] = emission[1];
  2614. gl_material->emission.v[2] = emission[2];
  2615. gl_material->emission.v[3] = emission[3];
  2616. gl_material->shininess = material->get_shininess();
  2617. gl_material->shininess_i = (int)((material->get_shininess() / 128.0f) * SPECULAR_BUFFER_RESOLUTION);
  2618. _color_material_flags = CMF_ambient | CMF_diffuse;
  2619. if (material->has_ambient()) {
  2620. const LColor &ambient = material->get_ambient();
  2621. gl_material->ambient.v[0] = ambient[0];
  2622. gl_material->ambient.v[1] = ambient[1];
  2623. gl_material->ambient.v[2] = ambient[2];
  2624. gl_material->ambient.v[3] = ambient[3];
  2625. _color_material_flags &= ~CMF_ambient;
  2626. }
  2627. if (material->has_diffuse()) {
  2628. const LColor &diffuse = material->get_diffuse();
  2629. gl_material->diffuse.v[0] = diffuse[0];
  2630. gl_material->diffuse.v[1] = diffuse[1];
  2631. gl_material->diffuse.v[2] = diffuse[2];
  2632. gl_material->diffuse.v[3] = diffuse[3];
  2633. _color_material_flags &= ~CMF_diffuse;
  2634. }
  2635. }
  2636. ////////////////////////////////////////////////////////////////////
  2637. // Function: TinyGraphicsStateGuardian::do_auto_rescale_normal
  2638. // Access: Protected
  2639. // Description: Sets the state to either rescale or normalize the
  2640. // normals according to the current transform.
  2641. ////////////////////////////////////////////////////////////////////
  2642. void TinyGraphicsStateGuardian::
  2643. do_auto_rescale_normal() {
  2644. if (_internal_transform->has_uniform_scale()) {
  2645. // There's a uniform scale; rescale the normals uniformly.
  2646. _c->normalize_enabled = false;
  2647. _c->normal_scale = _internal_transform->get_uniform_scale();
  2648. } else {
  2649. // If there's a non-uniform scale, normalize everything.
  2650. _c->normalize_enabled = true;
  2651. _c->normal_scale = 1.0f;
  2652. }
  2653. }
  2654. ////////////////////////////////////////////////////////////////////
  2655. // Function: TinyGraphicsStateGuardian::load_matrix
  2656. // Access: Private, Static
  2657. // Description: Copies the Panda matrix stored in the indicated
  2658. // TransformState object into the indicated TinyGL
  2659. // matrix.
  2660. ////////////////////////////////////////////////////////////////////
  2661. void TinyGraphicsStateGuardian::
  2662. load_matrix(M4 *matrix, const TransformState *transform) {
  2663. const LMatrix4 &pm = transform->get_mat();
  2664. for (int i = 0; i < 4; ++i) {
  2665. matrix->m[0][i] = pm.get_cell(i, 0);
  2666. matrix->m[1][i] = pm.get_cell(i, 1);
  2667. matrix->m[2][i] = pm.get_cell(i, 2);
  2668. matrix->m[3][i] = pm.get_cell(i, 3);
  2669. }
  2670. }
  2671. ////////////////////////////////////////////////////////////////////
  2672. // Function: TinyGraphicsStateGuardian::get_color_blend_op
  2673. // Access: Private, Static
  2674. // Description: Returns the integer element of store_pixel_funcs (as
  2675. // defined by store_pixel.py) that corresponds to the
  2676. // indicated ColorBlendAttrib operand code.
  2677. ////////////////////////////////////////////////////////////////////
  2678. int TinyGraphicsStateGuardian::
  2679. get_color_blend_op(ColorBlendAttrib::Operand operand) {
  2680. switch (operand) {
  2681. case ColorBlendAttrib::O_zero:
  2682. return 0;
  2683. case ColorBlendAttrib::O_one:
  2684. return 1;
  2685. case ColorBlendAttrib::O_incoming_color:
  2686. return 2;
  2687. case ColorBlendAttrib::O_one_minus_incoming_color:
  2688. return 3;
  2689. case ColorBlendAttrib::O_fbuffer_color:
  2690. return 4;
  2691. case ColorBlendAttrib::O_one_minus_fbuffer_color:
  2692. return 5;
  2693. case ColorBlendAttrib::O_incoming_alpha:
  2694. return 6;
  2695. case ColorBlendAttrib::O_one_minus_incoming_alpha:
  2696. return 7;
  2697. case ColorBlendAttrib::O_fbuffer_alpha:
  2698. return 8;
  2699. case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
  2700. return 9;
  2701. case ColorBlendAttrib::O_constant_color:
  2702. return 10;
  2703. case ColorBlendAttrib::O_one_minus_constant_color:
  2704. return 11;
  2705. case ColorBlendAttrib::O_constant_alpha:
  2706. return 12;
  2707. case ColorBlendAttrib::O_one_minus_constant_alpha:
  2708. return 13;
  2709. case ColorBlendAttrib::O_incoming_color_saturate:
  2710. return 1;
  2711. case ColorBlendAttrib::O_color_scale:
  2712. return 10;
  2713. case ColorBlendAttrib::O_one_minus_color_scale:
  2714. return 11;
  2715. case ColorBlendAttrib::O_alpha_scale:
  2716. return 12;
  2717. case ColorBlendAttrib::O_one_minus_alpha_scale:
  2718. return 13;
  2719. }
  2720. return 0;
  2721. }
  2722. ////////////////////////////////////////////////////////////////////
  2723. // Function: TinyGraphicsStateGuardian::get_tex_filter_func
  2724. // Access: Private, Static
  2725. // Description: Returns the pointer to the appropriate filter
  2726. // function according to the texture's filter type.
  2727. ////////////////////////////////////////////////////////////////////
  2728. ZB_lookupTextureFunc TinyGraphicsStateGuardian::
  2729. get_tex_filter_func(Texture::FilterType filter) {
  2730. switch (filter) {
  2731. case Texture::FT_nearest:
  2732. return &lookup_texture_nearest;
  2733. case Texture::FT_linear:
  2734. return &lookup_texture_bilinear;
  2735. case Texture::FT_nearest_mipmap_nearest:
  2736. return &lookup_texture_mipmap_nearest;
  2737. case Texture::FT_nearest_mipmap_linear:
  2738. return &lookup_texture_mipmap_linear;
  2739. case Texture::FT_linear_mipmap_nearest:
  2740. return &lookup_texture_mipmap_bilinear;
  2741. case Texture::FT_linear_mipmap_linear:
  2742. return &lookup_texture_mipmap_trilinear;
  2743. default:
  2744. return &lookup_texture_nearest;
  2745. }
  2746. }
  2747. ////////////////////////////////////////////////////////////////////
  2748. // Function: TinyGraphicsStateGuardian::get_tex_wrap_func
  2749. // Access: Private, Static
  2750. // Description: Returns the pointer to the appropriate wrap
  2751. // function according to the texture's wrap mode.
  2752. ////////////////////////////////////////////////////////////////////
  2753. ZB_texWrapFunc TinyGraphicsStateGuardian::
  2754. get_tex_wrap_func(Texture::WrapMode wrap_mode) {
  2755. switch (wrap_mode) {
  2756. case Texture::WM_clamp:
  2757. case Texture::WM_border_color: // border_color is handled later.
  2758. return &texcoord_clamp;
  2759. case Texture::WM_repeat:
  2760. case Texture::WM_invalid:
  2761. return &texcoord_repeat;
  2762. case Texture::WM_mirror:
  2763. return &texcoord_mirror;
  2764. case Texture::WM_mirror_once:
  2765. return &texcoord_mirror_once;
  2766. }
  2767. return &texcoord_repeat;
  2768. }
  2769. ////////////////////////////////////////////////////////////////////
  2770. // Function: TinyGraphicsStateGuardian::texgen_null
  2771. // Access: Private, Static
  2772. // Description: Generates invalid texture coordinates. Used when
  2773. // texture coordinate params are invalid or unsupported.
  2774. ////////////////////////////////////////////////////////////////////
  2775. void TinyGraphicsStateGuardian::
  2776. texgen_null(V2 &result, TinyGraphicsStateGuardian::TexCoordData &) {
  2777. result.v[0] = 0.0;
  2778. result.v[1] = 0.0;
  2779. }
  2780. ////////////////////////////////////////////////////////////////////
  2781. // Function: TinyGraphicsStateGuardian::texgen_simple
  2782. // Access: Private, Static
  2783. // Description: Extracts a simple 2-d texture coordinate pair from
  2784. // the vertex data, without applying any texture matrix.
  2785. ////////////////////////////////////////////////////////////////////
  2786. void TinyGraphicsStateGuardian::
  2787. texgen_simple(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
  2788. // No need to transform, so just extract as two-component.
  2789. const LVecBase2 &d = tcdata._r1.get_data2();
  2790. result.v[0] = d[0];
  2791. result.v[1] = d[1];
  2792. }
  2793. ////////////////////////////////////////////////////////////////////
  2794. // Function: TinyGraphicsStateGuardian::texgen_simple
  2795. // Access: Private, Static
  2796. // Description: Extracts a simple 2-d texture coordinate pair from
  2797. // the vertex data, and then applies a texture matrix.
  2798. ////////////////////////////////////////////////////////////////////
  2799. void TinyGraphicsStateGuardian::
  2800. texgen_texmat(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
  2801. // Transform texcoords as a four-component vector for most generality.
  2802. LVecBase4 d = tcdata._r1.get_data4() * tcdata._mat;
  2803. result.v[0] = d[0] / d[3];
  2804. result.v[1] = d[1] / d[3];
  2805. }
  2806. ////////////////////////////////////////////////////////////////////
  2807. // Function: TinyGraphicsStateGuardian::texgen_sphere_map
  2808. // Access: Private, Static
  2809. // Description: Computes appropriate sphere map texture coordinates
  2810. // based on the eye normal coordinates.
  2811. ////////////////////////////////////////////////////////////////////
  2812. void TinyGraphicsStateGuardian::
  2813. texgen_sphere_map(V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
  2814. // Get the normal and point in eye coordinates.
  2815. LVector3 n = tcdata._mat.xform_vec(tcdata._r1.get_data3());
  2816. LVector3 u = tcdata._mat.xform_point(tcdata._r2.get_data3());
  2817. // Normalize the vectors.
  2818. n.normalize();
  2819. u.normalize();
  2820. // Compute the reflection vector.
  2821. LVector3 r = u - n * dot(n, u) * 2.0f;
  2822. // compute the denominator, m.
  2823. PN_stdfloat m = 2.0f * csqrt(r[0] * r[0] + r[1] * r[1] + (r[2] + 1.0f) * (r[2] + 1.0f));
  2824. // Now we can compute the s and t coordinates.
  2825. result.v[0] = r[0] / m + 0.5f;
  2826. result.v[1] = r[1] / m + 0.5f;
  2827. /*
  2828. cerr << "n = " << n << " u = " << u << "\n"
  2829. << " r = " << r << "\n"
  2830. << " m = " << m << ", result = " << result.v[0] << " " << result.v[1]
  2831. << "\n";
  2832. */
  2833. }