15 #include "tinyGraphicsStateGuardian.h"
16 #include "tinyGeomMunger.h"
17 #include "tinyTextureContext.h"
18 #include "config_tinydisplay.h"
19 #include "pStatTimer.h"
20 #include "geomVertexReader.h"
21 #include "ambientLight.h"
22 #include "pointLight.h"
23 #include "directionalLight.h"
24 #include "spotlight.h"
25 #include "depthWriteAttrib.h"
26 #include "depthOffsetAttrib.h"
27 #include "colorWriteAttrib.h"
28 #include "alphaTestAttrib.h"
29 #include "depthTestAttrib.h"
30 #include "shadeModelAttrib.h"
31 #include "cullFaceAttrib.h"
32 #include "rescaleNormalAttrib.h"
33 #include "materialAttrib.h"
34 #include "lightAttrib.h"
35 #include "scissorAttrib.h"
37 #include "samplerState.h"
40 #include "ztriangle_table.h"
41 #include "store_pixel_table.h"
42 #include "graphicsEngine.h"
44 TypeHandle TinyGraphicsStateGuardian::_type_handle;
46 PStatCollector TinyGraphicsStateGuardian::_vertices_immediate_pcollector(
"Vertices:Immediate mode");
47 PStatCollector TinyGraphicsStateGuardian::_draw_transform_pcollector(
"Draw:Transform");
48 PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_untextured_pcollector(
"Pixels:White untextured");
49 PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_untextured_pcollector(
"Pixels:Flat untextured");
50 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_untextured_pcollector(
"Pixels:Smooth untextured");
51 PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_textured_pcollector(
"Pixels:White textured");
52 PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_textured_pcollector(
"Pixels:Flat textured");
53 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_textured_pcollector(
"Pixels:Smooth textured");
54 PStatCollector TinyGraphicsStateGuardian::_pixel_count_white_perspective_pcollector(
"Pixels:White perspective");
55 PStatCollector TinyGraphicsStateGuardian::_pixel_count_flat_perspective_pcollector(
"Pixels:Flat perspective");
56 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_perspective_pcollector(
"Pixels:Smooth perspective");
57 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_multitex2_pcollector(
"Pixels:Smooth multitex 2");
58 PStatCollector TinyGraphicsStateGuardian::_pixel_count_smooth_multitex3_pcollector(
"Pixels:Smooth multitex 3");
65 TinyGraphicsStateGuardian::
70 _current_frame_buffer = NULL;
71 _aux_frame_buffer = NULL;
82 TinyGraphicsStateGuardian::
83 ~TinyGraphicsStateGuardian() {
99 _inv_state_mask.clear_bit(ColorAttrib::get_class_slot());
100 _inv_state_mask.clear_bit(ColorScaleAttrib::get_class_slot());
101 _inv_state_mask.clear_bit(CullFaceAttrib::get_class_slot());
102 _inv_state_mask.clear_bit(DepthOffsetAttrib::get_class_slot());
103 _inv_state_mask.clear_bit(RenderModeAttrib::get_class_slot());
104 _inv_state_mask.clear_bit(RescaleNormalAttrib::get_class_slot());
105 _inv_state_mask.clear_bit(TextureAttrib::get_class_slot());
106 _inv_state_mask.clear_bit(MaterialAttrib::get_class_slot());
107 _inv_state_mask.clear_bit(LightAttrib::get_class_slot());
108 _inv_state_mask.clear_bit(ScissorAttrib::get_class_slot());
116 glInit(_c, _current_frame_buffer);
118 _c->draw_triangle_front = gl_draw_triangle_fill;
119 _c->draw_triangle_back = gl_draw_triangle_fill;
121 _supported_geom_rendering =
123 Geom::GR_indexed_other |
124 Geom::GR_triangle_strip |
125 Geom::GR_flat_last_vertex;
127 _max_texture_dimension = (1 << ZB_POINT_ST_FRAC_BITS);
128 _max_texture_stages = MAX_TEXTURE_STAGES;
129 _max_lights = MAX_LIGHTS;
131 _color_scale_via_lighting =
false;
132 _alpha_scale_via_texture =
false;
133 _runtime_color_scale =
true;
135 _color_material_flags = 0;
136 _texturing_state = 0;
137 _texfilter_state = 0;
138 _texture_replace =
false;
139 _filled_flat =
false;
140 _auto_rescale_normal =
false;
155 if (_aux_frame_buffer != (
ZBuffer *)NULL) {
156 ZB_close(_aux_frame_buffer);
157 _aux_frame_buffer = NULL;
160 if (_vertices != (
GLVertex *)NULL) {
161 PANDA_FREE_ARRAY(_vertices);
177 GraphicsStateGuardian::close_gsg();
207 return
GeomMunger::register_munger(munger, current_thread);
225 if ((!clearable->get_clear_color_active())&&
226 (!clearable->get_clear_depth_active())&&
227 (!clearable->get_clear_stencil_active())) {
231 set_state_and_transform(RenderState::make_empty(), _internal_transform);
233 bool clear_color =
false;
235 if (clearable->get_clear_color_active()) {
236 LColor v = clearable->get_clear_color();
239 if (_current_properties->get_srgb_color()) {
240 color = SRGBA_TO_PIXEL(
241 (v[0] * 0xffff), (v[1] * 0xffff),
242 (v[2] * 0xffff), (v[3] * 0xffff));
244 color = RGBA_TO_PIXEL(
245 (v[0] * 0xffff), (v[1] * 0xffff),
246 (v[2] * 0xffff), (v[3] * 0xffff));
251 bool clear_z =
false;
253 if (clearable->get_clear_depth_active()) {
259 ZB_clear_viewport(_c->zb, clear_z, z, clear_color, color,
260 _c->viewport.xmin, _c->viewport.ymin,
261 _c->viewport.xsize, _c->viewport.ysize);
275 int xmin, ymin, xsize, ysize;
278 PN_stdfloat pixel_factor = _current_display_region->get_pixel_factor();
279 if (pixel_factor != 1.0) {
284 xsize = int(xsize * pixel_factor);
285 ysize = int(ysize * pixel_factor);
286 if (_aux_frame_buffer == (
ZBuffer *)NULL) {
287 _aux_frame_buffer = ZB_open(xsize, ysize, ZB_MODE_RGBA, 0, 0, 0, 0);
288 }
else if (_aux_frame_buffer->xsize < xsize || _aux_frame_buffer->ysize < ysize) {
289 ZB_resize(_aux_frame_buffer, NULL,
290 max(_aux_frame_buffer->xsize, xsize),
291 max(_aux_frame_buffer->ysize, ysize));
293 _c->zb = _aux_frame_buffer;
297 _c->zb = _current_frame_buffer;
300 _c->viewport.xmin = xmin;
301 _c->viewport.ymin = ymin;
302 _c->viewport.xsize = xsize;
303 _c->viewport.ysize = ysize;
304 set_scissor(0.0f, 1.0f, 0.0f, 1.0f);
306 nassertv(xmin >= 0 && xmin < _c->zb->xsize &&
307 ymin >= 0 && ymin < _c->zb->ysize &&
308 xmin + xsize >= 0 && xmin + xsize <= _c->zb->xsize &&
309 ymin + ysize >= 0 && ymin + ysize <= _c->zb->ysize);
324 calc_projection_mat(const
Lens *lens) {
325 if (lens == (
Lens *)NULL) {
329 if (!lens->is_linear()) {
343 lens->get_projection_mat(_current_stereo_channel);
345 if (_scene_setup->get_inverted()) {
351 return TransformState::make_mat(result);
368 _transform_stale =
true;
391 _c->zb = _current_frame_buffer;
394 _vertices_immediate_pcollector.clear_level();
396 _pixel_count_white_untextured_pcollector.clear_level();
397 _pixel_count_flat_untextured_pcollector.clear_level();
398 _pixel_count_smooth_untextured_pcollector.clear_level();
399 _pixel_count_white_textured_pcollector.clear_level();
400 _pixel_count_flat_textured_pcollector.clear_level();
401 _pixel_count_smooth_textured_pcollector.clear_level();
402 _pixel_count_white_perspective_pcollector.clear_level();
403 _pixel_count_flat_perspective_pcollector.clear_level();
404 _pixel_count_smooth_perspective_pcollector.clear_level();
405 _pixel_count_smooth_multitex2_pcollector.clear_level();
406 _pixel_count_smooth_multitex3_pcollector.clear_level();
443 if (_c->zb == _aux_frame_buffer) {
446 int xmin, ymin, xsize, ysize;
447 _current_display_region->get_region_pixels_i(xmin, ymin, xsize, ysize);
448 PN_stdfloat pixel_factor = _current_display_region->get_pixel_factor();
450 int fb_xsize = int(xsize * pixel_factor);
451 int fb_ysize = int(ysize * pixel_factor);
453 ZB_zoomFrameBuffer(_current_frame_buffer, xmin, ymin, xsize, ysize,
454 _aux_frame_buffer, 0, 0, fb_xsize, fb_ysize);
455 _c->zb = _current_frame_buffer;
480 (
"td-show-zbuffer",
false,
481 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"));
482 if (td_show_zbuffer) {
483 PIXEL *tp = _current_frame_buffer->pbuf;
484 ZPOINT *tz = _current_frame_buffer->zbuf;
485 for (
int yi = 0; yi < _current_frame_buffer->ysize; ++yi) {
486 for (
int xi = 0; xi < _current_frame_buffer->xsize; ++xi) {
497 _vertices_immediate_pcollector.flush_level();
499 _pixel_count_white_untextured_pcollector.flush_level();
500 _pixel_count_flat_untextured_pcollector.flush_level();
501 _pixel_count_smooth_untextured_pcollector.flush_level();
502 _pixel_count_white_textured_pcollector.flush_level();
503 _pixel_count_flat_textured_pcollector.flush_level();
504 _pixel_count_smooth_textured_pcollector.flush_level();
505 _pixel_count_white_perspective_pcollector.flush_level();
506 _pixel_count_flat_perspective_pcollector.flush_level();
507 _pixel_count_smooth_perspective_pcollector.flush_level();
508 _pixel_count_smooth_multitex2_pcollector.flush_level();
509 _pixel_count_smooth_multitex3_pcollector.flush_level();
528 if (tinydisplay_cat.is_spam()) {
529 tinydisplay_cat.spam() <<
"begin_draw_primitives: " << *(data_reader->get_object()) <<
"\n";
541 if (_data_reader->is_vertex_transformed()) {
545 const TransformState *ident = TransformState::make_identity();
546 load_matrix(&_c->matrix_model_view, ident);
547 load_matrix(&_c->matrix_projection, _scissor_mat);
548 load_matrix(&_c->matrix_model_view_inv, ident);
549 load_matrix(&_c->matrix_model_projection, _scissor_mat);
550 _c->matrix_model_projection_no_w_transform = 1;
551 _transform_stale =
true;
553 }
else if (_transform_stale) {
556 CPT(TransformState) scissor_proj_mat = _scissor_mat->compose(_projection_mat);
558 if (_c->lighting_enabled) {
562 load_matrix(&_c->matrix_model_view, _internal_transform);
563 load_matrix(&_c->matrix_projection, scissor_proj_mat);
567 gl_M4_Inv(&tmp, &_c->matrix_model_view);
568 gl_M4_Transpose(&_c->matrix_model_view_inv, &tmp);
573 load_matrix(&_c->matrix_model_projection,
574 scissor_proj_mat->compose(_internal_transform));
577 _c->matrix_model_projection_no_w_transform = 0;
578 PN_stdfloat *m = &_c->matrix_model_projection.m[0][0];
579 if (m[12] == 0.0 && m[13] == 0.0 && m[14] == 0.0) {
580 _c->matrix_model_projection_no_w_transform = 1;
582 _transform_stale =
false;
587 int num_vertices = data_reader->get_num_rows();
588 _min_vertex = num_vertices;
590 int num_prims = geom_reader->get_num_primitives();
592 for (i = 0; i < num_prims; ++i) {
594 int nv = prim->get_min_vertex();
595 _min_vertex = min(_min_vertex, nv);
596 int xv = prim->get_max_vertex();
597 _max_vertex = max(_max_vertex, xv);
599 if (_min_vertex > _max_vertex) {
605 int num_used_vertices = _max_vertex - _min_vertex + 1;
606 if (_vertices_size < num_used_vertices) {
607 if (_vertices_size == 0) {
610 while (_vertices_size < num_used_vertices) {
613 if (_vertices != (
GLVertex *)NULL) {
614 PANDA_FREE_ARRAY(_vertices);
616 _vertices = (
GLVertex *)PANDA_MALLOC_ARRAY(_vertices_size *
sizeof(
GLVertex));
622 GenTexcoordFunc *texgen_func[MAX_TEXTURE_STAGES];
623 TexCoordData tcdata[MAX_TEXTURE_STAGES];
625 const TexGenAttrib *target_tex_gen = DCAST(
TexGenAttrib, _target_rs->get_attrib_def(TexGenAttrib::get_class_slot()));
628 int max_stage_index = _target_texture->get_num_on_ff_stages();
629 for (
int si = 0; si < max_stage_index; ++si) {
630 TextureStage *stage = _target_texture->get_on_ff_stage(si);
632 switch (target_tex_gen->
get_mode(stage)) {
633 case TexGenAttrib::M_eye_sphere_map:
638 texgen_func[si] = &texgen_sphere_map;
639 tcdata[si]._mat = _internal_transform->get_mat();
642 case TexGenAttrib::M_eye_position:
645 texgen_func[si] = &texgen_texmat;
647 CPT(TransformState) eye_transform =
648 _cs_transform->invert_compose(_internal_transform);
649 tcdata[si]._mat = eye_transform->get_mat();
651 if (target_tex_matrix->has_stage(stage)) {
652 tcdata[si]._mat = tcdata[si]._mat * target_tex_matrix->get_mat(stage);
656 case TexGenAttrib::M_world_position:
659 texgen_func[si] = &texgen_texmat;
661 CPT(TransformState) render_transform =
662 _cs_transform->compose(_scene_setup->get_world_transform());
663 CPT(TransformState) world_inv_transform =
664 render_transform->invert_compose(_internal_transform);
665 tcdata[si]._mat = world_inv_transform->get_mat();
667 if (target_tex_matrix->has_stage(stage)) {
668 tcdata[si]._mat = tcdata[si]._mat * target_tex_matrix->get_mat(stage);
676 texgen_func[si] = &texgen_simple;
677 if (target_tex_matrix->has_stage(stage)) {
678 texgen_func[si] = &texgen_texmat;
679 tcdata[si]._mat = target_tex_matrix->get_mat(stage);
684 tcdata[si]._r1.set_row_unsafe(_min_vertex);
685 tcdata[si]._r2.set_row_unsafe(_min_vertex);
686 if (!tcdata[si]._r1.has_column()) {
687 texgen_func[si] = &texgen_null;
691 bool needs_color =
false;
692 if (_vertex_colors_enabled) {
699 const LColor &d = _scene_graph_color;
700 const LColor &s = _current_color_scale;
701 _c->current_color.v[0] = max(d[0] * s[0], (PN_stdfloat)0);
702 _c->current_color.v[1] = max(d[1] * s[1], (PN_stdfloat)0);
703 _c->current_color.v[2] = max(d[2] * s[2], (PN_stdfloat)0);
704 _c->current_color.v[3] = max(d[3] * s[3], (PN_stdfloat)0);
707 bool needs_normal =
false;
708 if (_c->lighting_enabled) {
722 if (!needs_color && _color_material_flags) {
723 if (_color_material_flags & CMF_ambient) {
724 _c->materials[0].ambient = _c->current_color;
725 _c->materials[1].ambient = _c->current_color;
727 if (_color_material_flags & CMF_diffuse) {
728 _c->materials[0].diffuse = _c->current_color;
729 _c->materials[1].diffuse = _c->current_color;
733 if (_texturing_state != 0 && _texture_replace) {
737 needs_normal =
false;
740 bool lighting_enabled = (needs_normal && _c->lighting_enabled);
742 for (i = 0; i < num_used_vertices; ++i) {
746 v->coord.v[0] = d[0];
747 v->coord.v[1] = d[1];
748 v->coord.v[2] = d[2];
749 v->coord.v[3] = d[3];
752 for (
int si = 0; si < max_stage_index; ++si) {
754 (*texgen_func[si])(v->tex_coord[si], tcdata[si]);
759 const LColor &s = _current_color_scale;
760 _c->current_color.v[0] = max(d[0] * s[0], (PN_stdfloat)0);
761 _c->current_color.v[1] = max(d[1] * s[1], (PN_stdfloat)0);
762 _c->current_color.v[2] = max(d[2] * s[2], (PN_stdfloat)0);
763 _c->current_color.v[3] = max(d[3] * s[3], (PN_stdfloat)0);
765 if (_color_material_flags) {
766 if (_color_material_flags & CMF_ambient) {
767 _c->materials[0].ambient = _c->current_color;
768 _c->materials[1].ambient = _c->current_color;
770 if (_color_material_flags & CMF_diffuse) {
771 _c->materials[0].diffuse = _c->current_color;
772 _c->materials[1].diffuse = _c->current_color;
777 v->color = _c->current_color;
779 if (lighting_enabled) {
781 _c->current_normal.v[0] = d[0];
782 _c->current_normal.v[1] = d[1];
783 _c->current_normal.v[2] = d[2];
784 _c->current_normal.v[3] = 0.0f;
786 gl_vertex_transform(_c, v);
787 gl_shade_vertex(_c, v);
790 gl_vertex_transform(_c, v);
793 if (v->clip_code == 0) {
794 gl_transform_to_viewport(_c, v);
803 bool srgb_blend = _current_properties->get_srgb_color();
805 int depth_write_state = 0;
807 if (target_depth_write->
get_mode() != DepthWriteAttrib::M_on) {
808 depth_write_state = 1;
811 int color_write_state = 0;
814 unsigned int color_channels =
817 if (color_channels == ColorWriteAttrib::C_all) {
819 color_write_state = 4;
821 color_write_state = 0;
825 int op_a = get_color_blend_op(ColorBlendAttrib::O_one);
826 int op_b = get_color_blend_op(ColorBlendAttrib::O_zero);
829 _c->zb->store_pix_func = store_pixel_funcs_sRGB[op_a][op_b][color_channels];
831 _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
833 color_write_state = 2;
837 switch (target_transparency->
get_mode()) {
838 case TransparencyAttrib::M_alpha:
839 case TransparencyAttrib::M_dual:
840 if (color_channels == ColorWriteAttrib::C_all) {
842 color_write_state = 5;
844 color_write_state = 1;
848 int op_a = get_color_blend_op(ColorBlendAttrib::O_incoming_alpha);
849 int op_b = get_color_blend_op(ColorBlendAttrib::O_one_minus_incoming_alpha);
852 _c->zb->store_pix_func = store_pixel_funcs_sRGB[op_a][op_b][color_channels];
854 _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
856 color_write_state = 2;
865 if (target_color_blend->
get_mode() == ColorBlendAttrib::M_add) {
869 _c->zb->blend_r = (int)(c[0] * ZB_POINT_RED_MAX);
870 _c->zb->blend_g = (int)(c[1] * ZB_POINT_GREEN_MAX);
871 _c->zb->blend_b = (int)(c[2] * ZB_POINT_BLUE_MAX);
872 _c->zb->blend_a = (int)(c[3] * ZB_POINT_ALPHA_MAX);
874 int op_a = get_color_blend_op(target_color_blend->
get_operand_a());
875 int op_b = get_color_blend_op(target_color_blend->
get_operand_b());
878 _c->zb->store_pix_func = store_pixel_funcs_sRGB[op_a][op_b][color_channels];
880 _c->zb->store_pix_func = store_pixel_funcs[op_a][op_b][color_channels];
882 color_write_state = 2;
885 if (color_channels == ColorWriteAttrib::C_off) {
886 color_write_state = 3;
889 int alpha_test_state = 0;
891 switch (target_alpha_test->
get_mode()) {
892 case AlphaTestAttrib::M_none:
893 case AlphaTestAttrib::M_never:
894 case AlphaTestAttrib::M_always:
895 case AlphaTestAttrib::M_equal:
896 case AlphaTestAttrib::M_not_equal:
897 alpha_test_state = 0;
900 case AlphaTestAttrib::M_less:
901 case AlphaTestAttrib::M_less_equal:
902 alpha_test_state = 1;
903 _c->zb->reference_alpha = (int)(target_alpha_test->
get_reference_alpha() * ZB_POINT_ALPHA_MAX);
906 case AlphaTestAttrib::M_greater:
907 case AlphaTestAttrib::M_greater_equal:
908 alpha_test_state = 2;
909 _c->zb->reference_alpha = (int)(target_alpha_test->
get_reference_alpha() * ZB_POINT_ALPHA_MAX);
913 int depth_test_state = 1;
916 if (target_depth_test->
get_mode() == DepthTestAttrib::M_none) {
917 depth_test_state = 0;
922 ShadeModelAttrib::Mode shade_model = target_shade_model->
get_mode();
923 if (!needs_normal && !needs_color) {
926 shade_model = ShadeModelAttrib::M_flat;
928 int shade_model_state = 2;
929 _c->smooth_shade_model =
true;
931 if (shade_model == ShadeModelAttrib::M_flat) {
932 _c->smooth_shade_model =
false;
933 shade_model_state = 1;
934 if (_c->current_color.v[0] == 1.0f &&
935 _c->current_color.v[1] == 1.0f &&
936 _c->current_color.v[2] == 1.0f &&
937 _c->current_color.v[3] == 1.0f) {
938 shade_model_state = 0;
942 int texturing_state = _texturing_state;
943 int texfilter_state = 0;
944 if (texturing_state > 0) {
945 texfilter_state = _texfilter_state;
947 if (texturing_state < 3 &&
948 (_c->matrix_model_projection_no_w_transform || _filled_flat)) {
955 if (_texture_replace) {
958 shade_model_state = 0;
962 _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];
965 pixel_count_white_untextured = 0;
966 pixel_count_flat_untextured = 0;
967 pixel_count_smooth_untextured = 0;
968 pixel_count_white_textured = 0;
969 pixel_count_flat_textured = 0;
970 pixel_count_smooth_textured = 0;
971 pixel_count_white_perspective = 0;
972 pixel_count_flat_perspective = 0;
973 pixel_count_smooth_perspective = 0;
974 pixel_count_smooth_multitex2 = 0;
975 pixel_count_smooth_multitex3 = 0;
988 PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
991 if (tinydisplay_cat.is_spam()) {
992 tinydisplay_cat.spam() <<
"draw_triangles: " << *(reader->get_object()) <<
"\n";
996 int num_vertices = reader->get_num_vertices();
997 _vertices_tri_pcollector.add_level(num_vertices);
999 if (reader->is_indexed()) {
1000 switch (reader->get_index_type()) {
1001 case Geom::NT_uint8:
1003 PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
1004 if (index == NULL) {
1007 for (
int i = 0; i < num_vertices; i += 3) {
1008 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1009 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
1010 GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
1011 gl_draw_triangle(_c, v0, v1, v2);
1016 case Geom::NT_uint16:
1018 PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
1019 if (index == NULL) {
1022 for (
int i = 0; i < num_vertices; i += 3) {
1023 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1024 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
1025 GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
1026 gl_draw_triangle(_c, v0, v1, v2);
1031 case Geom::NT_uint32:
1033 PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
1034 if (index == NULL) {
1037 for (
int i = 0; i < num_vertices; i += 3) {
1038 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1039 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
1040 GLVertex *v2 = &_vertices[index[i + 2] - _min_vertex];
1041 gl_draw_triangle(_c, v0, v1, v2);
1047 tinydisplay_cat.error()
1048 <<
"Invalid index type " << reader->get_index_type() <<
"!\n";
1053 int delta = reader->get_first_vertex() - _min_vertex;
1054 for (
int vi = 0; vi < num_vertices; vi += 3) {
1055 GLVertex *v0 = &_vertices[vi + delta];
1056 GLVertex *v1 = &_vertices[vi + delta + 1];
1057 GLVertex *v2 = &_vertices[vi + delta + 2];
1058 gl_draw_triangle(_c, v0, v1, v2);
1072 PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
1075 if (tinydisplay_cat.is_spam()) {
1076 tinydisplay_cat.spam() <<
"draw_tristrips: " << *(reader->get_object()) <<
"\n";
1082 CPTA_int ends = reader->get_ends();
1084 _primitive_batches_tristrip_pcollector.add_level(ends.size());
1085 if (reader->is_indexed()) {
1086 unsigned int start = 0;
1087 for (
size_t i = 0; i < ends.size(); i++) {
1088 _vertices_tristrip_pcollector.add_level(ends[i] - start);
1091 nassertr(end - start >= 3,
false);
1093 switch (reader->get_index_type()) {
1094 case Geom::NT_uint8:
1096 PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
1097 if (index == NULL) {
1100 GLVertex *v0 = &_vertices[index[start] - _min_vertex];
1101 GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
1103 bool reversed =
false;
1104 for (
int vi = start + 2; vi < end; ++vi) {
1105 GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
1107 gl_draw_triangle(_c, v1, v0, v2);
1110 gl_draw_triangle(_c, v0, v1, v2);
1119 case Geom::NT_uint16:
1121 PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
1122 if (index == NULL) {
1125 GLVertex *v0 = &_vertices[index[start] - _min_vertex];
1126 GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
1128 bool reversed =
false;
1129 for (
int vi = start + 2; vi < end; ++vi) {
1130 GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
1132 gl_draw_triangle(_c, v1, v0, v2);
1135 gl_draw_triangle(_c, v0, v1, v2);
1144 case Geom::NT_uint32:
1146 PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
1147 if (index == NULL) {
1150 GLVertex *v0 = &_vertices[index[start] - _min_vertex];
1151 GLVertex *v1 = &_vertices[index[start + 1] - _min_vertex];
1153 bool reversed =
false;
1154 for (
int vi = start + 2; vi < end; ++vi) {
1155 GLVertex *v2 = &_vertices[index[vi] - _min_vertex];
1157 gl_draw_triangle(_c, v1, v0, v2);
1160 gl_draw_triangle(_c, v0, v1, v2);
1170 tinydisplay_cat.error()
1171 <<
"Invalid index type " << reader->get_index_type() <<
"!\n";
1175 start = ends[i] + 2;
1178 unsigned int start = 0;
1179 int delta = reader->get_first_vertex() - _min_vertex;
1180 for (
size_t i = 0; i < ends.size(); i++) {
1181 _vertices_tristrip_pcollector.add_level(ends[i] - start);
1184 nassertr(end - start >= 3,
false);
1185 GLVertex *v0 = &_vertices[start + delta];
1186 GLVertex *v1 = &_vertices[start + delta + 1];
1188 bool reversed =
false;
1189 for (
int vi = start + 2; vi < end; ++vi) {
1190 GLVertex *v2 = &_vertices[vi + delta];
1192 gl_draw_triangle(_c, v1, v0, v2);
1195 gl_draw_triangle(_c, v0, v1, v2);
1201 start = ends[i] + 2;
1215 PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
1217 if (tinydisplay_cat.is_spam()) {
1218 tinydisplay_cat.spam() <<
"draw_lines: " << *(reader->get_object()) <<
"\n";
1222 int num_vertices = reader->get_num_vertices();
1223 _vertices_other_pcollector.add_level(num_vertices);
1225 if (reader->is_indexed()) {
1226 switch (reader->get_index_type()) {
1227 case Geom::NT_uint8:
1229 PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
1230 if (index == NULL) {
1233 for (
int i = 0; i < num_vertices; i += 2) {
1234 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1235 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
1236 gl_draw_line(_c, v0, v1);
1241 case Geom::NT_uint16:
1243 PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
1244 if (index == NULL) {
1247 for (
int i = 0; i < num_vertices; i += 2) {
1248 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1249 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
1250 gl_draw_line(_c, v0, v1);
1255 case Geom::NT_uint32:
1257 PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
1258 if (index == NULL) {
1261 for (
int i = 0; i < num_vertices; i += 2) {
1262 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1263 GLVertex *v1 = &_vertices[index[i + 1] - _min_vertex];
1264 gl_draw_line(_c, v0, v1);
1270 tinydisplay_cat.error()
1271 <<
"Invalid index type " << reader->get_index_type() <<
"!\n";
1276 int delta = reader->get_first_vertex() - _min_vertex;
1277 for (
int vi = 0; vi < num_vertices; vi += 2) {
1278 GLVertex *v0 = &_vertices[vi + delta];
1279 GLVertex *v1 = &_vertices[vi + delta + 1];
1280 gl_draw_line(_c, v0, v1);
1294 PStatTimer timer(_draw_primitive_pcollector, reader->get_current_thread());
1296 if (tinydisplay_cat.is_spam()) {
1297 tinydisplay_cat.spam() <<
"draw_points: " << *(reader->get_object()) <<
"\n";
1301 int num_vertices = reader->get_num_vertices();
1302 _vertices_other_pcollector.add_level(num_vertices);
1304 if (reader->is_indexed()) {
1305 switch (reader->get_index_type()) {
1306 case Geom::NT_uint8:
1308 PN_uint8 *index = (PN_uint8 *)reader->get_read_pointer(force);
1309 if (index == NULL) {
1312 for (
int i = 0; i < num_vertices; ++i) {
1313 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1314 gl_draw_point(_c, v0);
1319 case Geom::NT_uint16:
1321 PN_uint16 *index = (PN_uint16 *)reader->get_read_pointer(force);
1322 if (index == NULL) {
1325 for (
int i = 0; i < num_vertices; ++i) {
1326 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1327 gl_draw_point(_c, v0);
1332 case Geom::NT_uint32:
1334 PN_uint32 *index = (PN_uint32 *)reader->get_read_pointer(force);
1335 if (index == NULL) {
1338 for (
int i = 0; i < num_vertices; ++i) {
1339 GLVertex *v0 = &_vertices[index[i] - _min_vertex];
1340 gl_draw_point(_c, v0);
1346 tinydisplay_cat.error()
1347 <<
"Invalid index type " << reader->get_index_type() <<
"!\n";
1352 int delta = reader->get_first_vertex() - _min_vertex;
1353 for (
int vi = 0; vi < num_vertices; ++vi) {
1354 GLVertex *v0 = &_vertices[vi + delta];
1355 gl_draw_point(_c, v0);
1373 _pixel_count_white_untextured_pcollector.add_level(pixel_count_white_untextured);
1374 _pixel_count_flat_untextured_pcollector.add_level(pixel_count_flat_untextured);
1375 _pixel_count_smooth_untextured_pcollector.add_level(pixel_count_smooth_untextured);
1376 _pixel_count_white_textured_pcollector.add_level(pixel_count_white_textured);
1377 _pixel_count_flat_textured_pcollector.add_level(pixel_count_flat_textured);
1378 _pixel_count_smooth_textured_pcollector.add_level(pixel_count_smooth_textured);
1379 _pixel_count_white_perspective_pcollector.add_level(pixel_count_white_perspective);
1380 _pixel_count_flat_perspective_pcollector.add_level(pixel_count_flat_perspective);
1381 _pixel_count_smooth_perspective_pcollector.add_level(pixel_count_smooth_perspective);
1382 _pixel_count_smooth_multitex2_pcollector.add_level(pixel_count_smooth_multitex2);
1383 _pixel_count_smooth_multitex3_pcollector.add_level(pixel_count_smooth_multitex3);
1402 nassertr(tex != NULL && dr != NULL,
false);
1419 gltex->border_color.v[0] = border_color[0];
1420 gltex->border_color.v[1] = border_color[1];
1421 gltex->border_color.v[2] = border_color[2];
1422 gltex->border_color.v[3] = border_color[3];
1424 PIXEL *ip = gltex->levels[0].pixmap + gltex->xsize * gltex->ysize;
1425 PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
1426 for (
int y = 0; y < gltex->ysize; ++y) {
1428 memcpy(ip, fo, gltex->xsize * PSZB);
1429 fo += _c->zb->linesize / PSZB;
1434 gtc->
enqueue_lru(&_prepared_objects->_graphics_memory_lru);
1453 nassertr(tex != NULL && dr != NULL,
false);
1458 Texture::TextureType texture_type;
1461 texture_type = Texture::TT_cube_map;
1464 texture_type = Texture::TT_2d_texture;
1468 Texture::ComponentType component_type = Texture::T_unsigned_byte;
1469 Texture::Format format = Texture::F_rgba;
1478 component_type, format);
1481 nassertr(z < tex->get_z_size(),
false);
1485 if (z >= 0 || view > 0) {
1488 image_ptr += z * image_size;
1491 image_ptr += (view * tex->
get_z_size()) * image_size;
1495 PIXEL *ip = (PIXEL *)(image_ptr + image_size);
1496 PIXEL *fo = _c->zb->pbuf + xo + yo * _c->zb->linesize / PSZB;
1497 for (
int y = 0; y < h; ++y) {
1499 #ifndef WORDS_BIGENDIAN
1501 memcpy(ip, fo, w * PSZB);
1504 const char *source = (
const char *)fo;
1505 const char *stop = (
const char *)fo + w * PSZB;
1506 char *dest = (
char *)ip;
1507 while (source < stop) {
1520 fo += _c->zb->linesize / PSZB;
1545 const TransformState *transform) {
1547 if (tinydisplay_cat.is_spam()) {
1548 tinydisplay_cat.spam()
1549 <<
"Setting GSG state to " << (
void *)target <<
":\n";
1550 target->write(tinydisplay_cat.spam(
false), 2);
1551 transform->write(tinydisplay_cat.spam(
false), 2);
1555 _state_pcollector.add_level(1);
1556 PStatTimer timer1(_draw_set_state_pcollector);
1558 if (transform != _internal_transform) {
1559 PStatTimer timer(_draw_set_state_transform_pcollector);
1560 _state_pcollector.add_level(1);
1561 _internal_transform = transform;
1562 do_issue_transform();
1565 if (target == _state_rs && (_state_mask | _inv_state_mask).is_all_on()) {
1568 _target_rs = target;
1570 int color_slot = ColorAttrib::get_class_slot();
1571 int color_scale_slot = ColorScaleAttrib::get_class_slot();
1572 if (_target_rs->get_attrib(color_slot) != _state_rs->get_attrib(color_slot) ||
1573 _target_rs->get_attrib(color_scale_slot) != _state_rs->get_attrib(color_scale_slot) ||
1574 !_state_mask.get_bit(color_slot) ||
1575 !_state_mask.get_bit(color_scale_slot)) {
1576 PStatTimer timer(_draw_set_state_color_pcollector);
1578 do_issue_color_scale();
1579 _state_mask.set_bit(color_slot);
1580 _state_mask.set_bit(color_scale_slot);
1583 int cull_face_slot = CullFaceAttrib::get_class_slot();
1584 if (_target_rs->get_attrib(cull_face_slot) != _state_rs->get_attrib(cull_face_slot) ||
1585 !_state_mask.get_bit(cull_face_slot)) {
1586 PStatTimer timer(_draw_set_state_cull_face_pcollector);
1587 do_issue_cull_face();
1588 _state_mask.set_bit(cull_face_slot);
1591 int depth_offset_slot = DepthOffsetAttrib::get_class_slot();
1592 if (_target_rs->get_attrib(depth_offset_slot) != _state_rs->get_attrib(depth_offset_slot) ||
1593 !_state_mask.get_bit(depth_offset_slot)) {
1595 do_issue_depth_offset();
1596 _state_mask.set_bit(depth_offset_slot);
1599 int rescale_normal_slot = RescaleNormalAttrib::get_class_slot();
1600 if (_target_rs->get_attrib(rescale_normal_slot) != _state_rs->get_attrib(rescale_normal_slot) ||
1601 !_state_mask.get_bit(rescale_normal_slot)) {
1602 PStatTimer timer(_draw_set_state_rescale_normal_pcollector);
1603 do_issue_rescale_normal();
1604 _state_mask.set_bit(rescale_normal_slot);
1607 int render_mode_slot = RenderModeAttrib::get_class_slot();
1608 if (_target_rs->get_attrib(render_mode_slot) != _state_rs->get_attrib(render_mode_slot) ||
1609 !_state_mask.get_bit(render_mode_slot)) {
1610 PStatTimer timer(_draw_set_state_render_mode_pcollector);
1611 do_issue_render_mode();
1612 _state_mask.set_bit(render_mode_slot);
1615 int texture_slot = TextureAttrib::get_class_slot();
1616 if (_target_rs->get_attrib(texture_slot) != _state_rs->get_attrib(texture_slot) ||
1617 !_state_mask.get_bit(texture_slot)) {
1618 PStatTimer timer(_draw_set_state_texture_pcollector);
1619 determine_target_texture();
1621 _state_mask.set_bit(texture_slot);
1624 int material_slot = MaterialAttrib::get_class_slot();
1625 if (_target_rs->get_attrib(material_slot) != _state_rs->get_attrib(material_slot) ||
1626 !_state_mask.get_bit(material_slot)) {
1627 PStatTimer timer(_draw_set_state_material_pcollector);
1628 do_issue_material();
1629 _state_mask.set_bit(material_slot);
1632 int light_slot = LightAttrib::get_class_slot();
1633 if (_target_rs->get_attrib(light_slot) != _state_rs->get_attrib(light_slot) ||
1634 !_state_mask.get_bit(light_slot)) {
1635 PStatTimer timer(_draw_set_state_light_pcollector);
1637 _state_mask.set_bit(light_slot);
1640 int scissor_slot = ScissorAttrib::get_class_slot();
1641 if (_target_rs->get_attrib(scissor_slot) != _state_rs->get_attrib(scissor_slot) ||
1642 !_state_mask.get_bit(scissor_slot)) {
1643 PStatTimer timer(_draw_set_state_scissor_pcollector);
1645 _state_mask.set_bit(scissor_slot);
1648 _state_rs = _target_rs;
1667 case Texture::TT_1d_texture:
1668 case Texture::TT_2d_texture:
1674 tinydisplay_cat.info()
1675 <<
"Not loading texture " << tex->get_name() <<
": "
1724 bool okflag = upload_texture(gtc, force, tex->
uses_mipmaps());
1726 tinydisplay_cat.error()
1727 <<
"Could not load " << *tex <<
"\n";
1731 gtc->
enqueue_lru(&_prepared_objects->_graphics_memory_lru);
1761 if (uses_mipmaps && gltex->num_levels <= 1) {
1764 bool okflag = upload_texture(gtc, force,
true);
1766 tinydisplay_cat.error()
1767 <<
"Could not load " << *tex <<
"\n";
1772 _c->current_textures[stage_index] = gltex;
1774 ZTextureDef *texture_def = &_c->zb->current_textures[stage_index];
1775 texture_def->levels = gltex->levels;
1776 texture_def->s_max = gltex->s_max;
1777 texture_def->t_max = gltex->t_max;
1779 const V4 &bc = gltex->border_color;
1780 int r = (int)(bc.v[0] * (ZB_POINT_RED_MAX - ZB_POINT_RED_MIN)
1781 + ZB_POINT_RED_MIN);
1782 int g = (int)(bc.v[1] * (ZB_POINT_GREEN_MAX - ZB_POINT_GREEN_MIN)
1783 + ZB_POINT_GREEN_MIN);
1784 int b = (int)(bc.v[2] * (ZB_POINT_BLUE_MAX - ZB_POINT_BLUE_MIN)
1785 + ZB_POINT_BLUE_MIN);
1786 int a = (int)(bc.v[3] * (ZB_POINT_ALPHA_MAX - ZB_POINT_ALPHA_MIN)
1787 + ZB_POINT_ALPHA_MIN);
1788 texture_def->border_color = RGBA_TO_PIXEL(r, g, b, a);
1805 _texturing_state = 0;
1808 if (gltex->allocated_buffer != NULL) {
1809 nassertv(gltex->num_levels != 0);
1810 TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
1811 PANDA_FREE_ARRAY(gltex->allocated_buffer);
1812 gltex->allocated_buffer = NULL;
1813 gltex->total_bytecount = 0;
1814 gltex->num_levels = 0;
1816 nassertv(gltex->num_levels == 0);
1833 LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
1835 int num_enabled = 0;
1836 int num_on_lights = 0;
1838 const LightAttrib *target_light = DCAST(
LightAttrib, _target_rs->get_attrib_def(LightAttrib::get_class_slot()));
1839 if (display_cat.is_spam()) {
1841 <<
"do_issue_light: " << target_light <<
"\n";
1845 clear_light_state();
1849 CPT(
LightAttrib) new_light = target_light->filter_to_max(_max_lights);
1850 if (display_cat.is_spam()) {
1851 new_light->write(display_cat.spam(
false), 2);
1854 num_on_lights = new_light->get_num_on_lights();
1855 for (
int li = 0; li < num_on_lights; li++) {
1856 NodePath light = new_light->get_on_light(li);
1859 nassertv(light_obj != (
Light *)NULL);
1861 _lighting_enabled =
true;
1862 _c->lighting_enabled =
true;
1864 if (light_obj->get_type() == AmbientLight::get_class_type()) {
1866 cur_ambient_light += light_obj->get_color();
1870 light_obj->bind(
this, light, num_enabled);
1875 GLLight *gl_light = _c->first_light;
1876 nassertv(gl_light != NULL);
1877 const LColor &diffuse = light_obj->get_color();
1878 gl_light->diffuse.v[0] = diffuse[0];
1879 gl_light->diffuse.v[1] = diffuse[1];
1880 gl_light->diffuse.v[2] = diffuse[2];
1881 gl_light->diffuse.v[3] = diffuse[3];
1886 _c->ambient_light_model.v[0] = cur_ambient_light[0];
1887 _c->ambient_light_model.v[1] = cur_ambient_light[1];
1888 _c->ambient_light_model.v[2] = cur_ambient_light[2];
1889 _c->ambient_light_model.v[3] = cur_ambient_light[3];
1893 _transform_stale =
true;
1906 pair<Lights::iterator, bool> lookup = _plights.insert(Lights::value_type(light,
GLLight()));
1907 GLLight *gl_light = &(*lookup.first).second;
1908 if (lookup.second) {
1910 memset(gl_light, 0,
sizeof(
GLLight));
1913 gl_light->specular.v[0] = specular[0];
1914 gl_light->specular.v[1] = specular[1];
1915 gl_light->specular.v[2] = specular[2];
1916 gl_light->specular.v[3] = specular[3];
1920 CPT(TransformState) render_transform =
1921 _cs_transform->compose(_scene_setup->get_world_transform());
1923 CPT(TransformState) transform = light.
get_transform(_scene_setup->get_scene_root().get_parent());
1924 CPT(TransformState) net_transform = render_transform->compose(transform);
1927 gl_light->position.v[0] = pos[0];
1928 gl_light->position.v[1] = pos[1];
1929 gl_light->position.v[2] = pos[2];
1930 gl_light->position.v[3] = 1.0f;
1933 gl_light->spot_exponent = 0.0f;
1936 gl_light->spot_cutoff = 180.0f;
1939 gl_light->attenuation[0] = att[0];
1940 gl_light->attenuation[1] = att[1];
1941 gl_light->attenuation[2] = att[2];
1944 nassertv(gl_light->next == NULL);
1947 gl_light->next = _c->first_light;
1948 _c->first_light = gl_light;
1961 pair<Lights::iterator, bool> lookup = _dlights.insert(Lights::value_type(light,
GLLight()));
1962 GLLight *gl_light = &(*lookup.first).second;
1963 if (lookup.second) {
1965 memset(gl_light, 0,
sizeof(
GLLight));
1968 gl_light->specular.v[0] = specular[0];
1969 gl_light->specular.v[1] = specular[1];
1970 gl_light->specular.v[2] = specular[2];
1971 gl_light->specular.v[3] = specular[3];
1975 CPT(TransformState) render_transform =
1976 _cs_transform->compose(_scene_setup->get_world_transform());
1978 CPT(TransformState) transform = light.
get_transform(_scene_setup->get_scene_root().get_parent());
1979 CPT(TransformState) net_transform = render_transform->compose(transform);
1983 gl_light->position.v[0] = -dir[0];
1984 gl_light->position.v[1] = -dir[1];
1985 gl_light->position.v[2] = -dir[2];
1986 gl_light->position.v[3] = 0.0f;
1988 gl_light->norm_position.v[0] = -dir[0];
1989 gl_light->norm_position.v[1] = -dir[1];
1990 gl_light->norm_position.v[2] = -dir[2];
1991 gl_V3_Norm(&gl_light->norm_position);
1994 gl_light->spot_exponent = 0.0f;
1997 gl_light->spot_cutoff = 180.0f;
2001 gl_light->attenuation[0] = 1.0f;
2002 gl_light->attenuation[1] = 0.0f;
2003 gl_light->attenuation[2] = 0.0f;
2006 nassertv(gl_light->next == NULL);
2009 gl_light->next = _c->first_light;
2010 _c->first_light = gl_light;
2023 pair<Lights::iterator, bool> lookup = _plights.insert(Lights::value_type(light,
GLLight()));
2024 GLLight *gl_light = &(*lookup.first).second;
2025 if (lookup.second) {
2027 memset(gl_light, 0,
sizeof(
GLLight));
2030 gl_light->specular.v[0] = specular[0];
2031 gl_light->specular.v[1] = specular[1];
2032 gl_light->specular.v[2] = specular[2];
2033 gl_light->specular.v[3] = specular[3];
2036 nassertv(lens != (
Lens *)NULL);
2040 CPT(TransformState) render_transform =
2041 _cs_transform->compose(_scene_setup->get_world_transform());
2043 CPT(TransformState) transform = light.
get_transform(_scene_setup->get_scene_root().get_parent());
2044 CPT(TransformState) net_transform = render_transform->compose(transform);
2046 const LMatrix4 &light_mat = net_transform->get_mat();
2051 gl_light->position.v[0] = pos[0];
2052 gl_light->position.v[1] = pos[1];
2053 gl_light->position.v[2] = pos[2];
2054 gl_light->position.v[3] = 1.0f;
2056 gl_light->spot_direction.v[0] = dir[0];
2057 gl_light->spot_direction.v[1] = dir[1];
2058 gl_light->spot_direction.v[2] = dir[2];
2060 gl_light->norm_spot_direction.v[0] = dir[0];
2061 gl_light->norm_spot_direction.v[1] = dir[1];
2062 gl_light->norm_spot_direction.v[2] = dir[2];
2063 gl_V3_Norm(&gl_light->norm_spot_direction);
2066 gl_light->spot_cutoff = lens->
get_hfov() * 0.5f;
2069 gl_light->attenuation[0] = att[0];
2070 gl_light->attenuation[1] = att[1];
2071 gl_light->attenuation[2] = att[2];
2074 nassertv(gl_light->next == NULL);
2077 gl_light->next = _c->first_light;
2078 _c->first_light = gl_light;
2090 void TinyGraphicsStateGuardian::
2091 do_issue_transform() {
2092 _transform_state_pcollector.add_level(1);
2093 _transform_stale =
true;
2095 if (_auto_rescale_normal) {
2096 do_auto_rescale_normal();
2105 void TinyGraphicsStateGuardian::
2106 do_issue_render_mode() {
2109 _filled_flat =
false;
2111 switch (target_render_mode->
get_mode()) {
2112 case RenderModeAttrib::M_unchanged:
2113 case RenderModeAttrib::M_filled:
2114 _c->draw_triangle_front = gl_draw_triangle_fill;
2115 _c->draw_triangle_back = gl_draw_triangle_fill;
2118 case RenderModeAttrib::M_filled_flat:
2119 _c->draw_triangle_front = gl_draw_triangle_fill;
2120 _c->draw_triangle_back = gl_draw_triangle_fill;
2121 _filled_flat =
true;
2124 case RenderModeAttrib::M_wireframe:
2125 _c->draw_triangle_front = gl_draw_triangle_line;
2126 _c->draw_triangle_back = gl_draw_triangle_line;
2129 case RenderModeAttrib::M_point:
2130 _c->draw_triangle_front = gl_draw_triangle_point;
2131 _c->draw_triangle_back = gl_draw_triangle_point;
2135 tinydisplay_cat.error()
2136 <<
"Unknown render mode " << (int)target_render_mode->
get_mode() << endl;
2145 void TinyGraphicsStateGuardian::
2146 do_issue_rescale_normal() {
2148 RescaleNormalAttrib::Mode mode = target_rescale_normal->
get_mode();
2150 _auto_rescale_normal =
false;
2153 case RescaleNormalAttrib::M_none:
2154 _c->normalize_enabled =
false;
2155 _c->normal_scale = 1.0f;
2158 case RescaleNormalAttrib::M_normalize:
2159 _c->normalize_enabled =
true;
2160 _c->normal_scale = 1.0f;
2163 case RescaleNormalAttrib::M_rescale:
2164 case RescaleNormalAttrib::M_auto:
2165 _auto_rescale_normal =
true;
2166 do_auto_rescale_normal();
2170 tinydisplay_cat.error()
2171 <<
"Unknown rescale_normal mode " << (int)mode << endl;
2180 void TinyGraphicsStateGuardian::
2181 do_issue_depth_offset() {
2183 int offset = target_depth_offset->
get_offset();
2186 PN_stdfloat min_value = target_depth_offset->
get_min_value();
2187 PN_stdfloat max_value = target_depth_offset->
get_max_value();
2188 if (min_value == 0.0f && max_value == 1.0f) {
2189 _c->has_zrange =
false;
2191 _c->has_zrange =
true;
2192 _c->zmin = min_value;
2193 _c->zrange = max_value - min_value;
2202 void TinyGraphicsStateGuardian::
2203 do_issue_cull_face() {
2208 case CullFaceAttrib::M_cull_none:
2209 _c->cull_face_enabled =
false;
2211 case CullFaceAttrib::M_cull_clockwise:
2212 _c->cull_face_enabled =
true;
2213 _c->cull_clockwise =
true;
2215 case CullFaceAttrib::M_cull_counter_clockwise:
2216 _c->cull_face_enabled =
true;
2217 _c->cull_clockwise =
false;
2220 tinydisplay_cat.error()
2221 <<
"invalid cull face mode " << (int)mode << endl;
2231 void TinyGraphicsStateGuardian::
2232 do_issue_material() {
2239 target_material->
is_off()) {
2246 setup_material(&_c->materials[0], material);
2248 if (material->get_twoside()) {
2250 setup_material(&_c->materials[1], material);
2253 _c->local_light_model = material->get_local();
2254 _c->light_model_two_side = material->get_twoside();
2262 void TinyGraphicsStateGuardian::
2263 do_issue_texture() {
2264 _texturing_state = 0;
2265 _c->num_textures_enabled = 0;
2267 int num_stages = _target_texture->get_num_on_ff_stages();
2268 if (num_stages == 0) {
2272 nassertv(num_stages <= MAX_TEXTURE_STAGES);
2274 bool all_replace =
true;
2275 bool all_nearest =
true;
2276 bool all_mipmap_nearest =
true;
2277 bool any_mipmap =
false;
2278 bool needs_general =
false;
2279 Texture::QualityLevel best_quality_level = Texture::QL_default;
2281 for (
int si = 0; si < num_stages; ++si) {
2282 TextureStage *stage = _target_texture->get_on_ff_stage(si);
2283 Texture *texture = _target_texture->get_on_texture(stage);
2284 nassertv(texture != (
Texture *)NULL);
2294 const SamplerState &sampler = _target_texture->get_on_sampler(stage);
2303 if (stage->
get_mode() != TextureStage::M_replace) {
2304 all_replace =
false;
2307 Texture::QualityLevel quality_level = _texture_quality_override;
2308 if (quality_level == Texture::QL_default) {
2311 if (quality_level == Texture::QL_default) {
2312 quality_level = texture_quality_level;
2315 best_quality_level = max(best_quality_level, quality_level);
2317 ZTextureDef *texture_def = &_c->zb->current_textures[si];
2321 SamplerState::FilterType minfilter = sampler.
get_minfilter();
2322 SamplerState::FilterType magfilter = sampler.
get_magfilter();
2326 if (minfilter == SamplerState::FT_nearest_mipmap_nearest) {
2327 minfilter = SamplerState::FT_nearest;
2329 minfilter = SamplerState::FT_linear;
2335 if (quality_level == Texture::QL_fastest) {
2336 minfilter = SamplerState::FT_nearest;
2337 magfilter = SamplerState::FT_nearest;
2339 }
else if (quality_level == Texture::QL_normal) {
2341 minfilter = SamplerState::FT_nearest_mipmap_nearest;
2343 minfilter = SamplerState::FT_nearest;
2345 magfilter = SamplerState::FT_nearest;
2347 }
else if (quality_level == Texture::QL_best) {
2352 texture_def->tex_minfilter_func = get_tex_filter_func(minfilter);
2353 texture_def->tex_magfilter_func = get_tex_filter_func(magfilter);
2355 SamplerState::WrapMode wrap_u = sampler.
get_wrap_u();
2356 SamplerState::WrapMode wrap_v = sampler.
get_wrap_v();
2357 if (td_ignore_clamp) {
2358 wrap_u = SamplerState::WM_repeat;
2359 wrap_v = SamplerState::WM_repeat;
2362 if (wrap_u != SamplerState::WM_repeat || wrap_v != SamplerState::WM_repeat) {
2365 needs_general =
true;
2372 texture_def->tex_minfilter_func_impl = texture_def->tex_minfilter_func;
2373 texture_def->tex_magfilter_func_impl = texture_def->tex_magfilter_func;
2377 texture_def->tex_minfilter_func = apply_wrap_general_minfilter;
2378 texture_def->tex_magfilter_func = apply_wrap_general_magfilter;
2380 texture_def->tex_wrap_u_func = get_tex_wrap_func(wrap_u);
2381 texture_def->tex_wrap_v_func = get_tex_wrap_func(wrap_v);
2385 if (wrap_u && SamplerState::WM_border_color && wrap_v == SamplerState::WM_border_color) {
2386 texture_def->tex_minfilter_func = apply_wrap_border_color_minfilter;
2387 texture_def->tex_magfilter_func = apply_wrap_border_color_magfilter;
2388 }
else if (wrap_u && SamplerState::WM_clamp && wrap_v == SamplerState::WM_clamp) {
2389 texture_def->tex_minfilter_func = apply_wrap_clamp_minfilter;
2390 texture_def->tex_magfilter_func = apply_wrap_clamp_magfilter;
2394 if (minfilter != SamplerState::FT_nearest || magfilter != SamplerState::FT_nearest) {
2395 all_nearest =
false;
2398 if (minfilter != SamplerState::FT_nearest_mipmap_nearest ||
2399 magfilter != SamplerState::FT_nearest) {
2400 all_mipmap_nearest =
false;
2409 _c->num_textures_enabled = num_stages;
2410 _texture_replace = all_replace;
2412 _texturing_state = 2;
2413 if (num_stages >= 3) {
2414 _texturing_state = 4;
2415 }
else if (num_stages == 2) {
2416 _texturing_state = 3;
2417 }
else if (!td_perspective_textures) {
2418 _texturing_state = 1;
2421 if (best_quality_level == Texture::QL_best) {
2423 _texfilter_state = 2;
2425 if (!needs_general) {
2428 _texfilter_state = 0;
2429 }
else if (all_mipmap_nearest) {
2431 _texfilter_state = 1;
2435 }
else if (best_quality_level == Texture::QL_fastest) {
2438 _texfilter_state = 0;
2439 _texturing_state = 1;
2445 _texfilter_state = 0;
2447 _texfilter_state = 1;
2450 if (needs_general) {
2453 _texfilter_state = 2;
2463 void TinyGraphicsStateGuardian::
2464 do_issue_scissor() {
2467 set_scissor(frame[0], frame[1], frame[2], frame[3]);
2476 void TinyGraphicsStateGuardian::
2477 set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
2478 _c->scissor.left = left;
2479 _c->scissor.right = right;
2480 _c->scissor.bottom = bottom;
2481 _c->scissor.top = top;
2482 gl_eval_viewport(_c);
2484 PN_stdfloat xsize = right - left;
2485 PN_stdfloat ysize = top - bottom;
2486 PN_stdfloat xcenter = (left + right) - 1.0f;
2487 PN_stdfloat ycenter = (bottom + top) - 1.0f;
2488 if (xsize == 0.0f || ysize == 0.0f) {
2491 _scissor_mat = TransformState::make_identity();
2493 _scissor_mat = TransformState::make_scale(
LVecBase3(1.0f / xsize, 1.0f / ysize, 1.0f))->compose(TransformState::make_pos(
LPoint3(-xcenter, -ycenter, 0.0f)));
2504 bool TinyGraphicsStateGuardian::
2520 bool TinyGraphicsStateGuardian::
2524 if (_effective_incomplete_render && !force) {
2527 !_loader.is_null()) {
2530 async_reload_texture(gtc);
2533 return upload_simple_texture(gtc);
2559 if (tinydisplay_cat.is_debug()) {
2560 tinydisplay_cat.debug()
2561 <<
"loading texture " << tex->get_name() <<
", "
2563 << num_levels <<
", uses_mipmaps = " << uses_mipmaps <<
"\n";
2571 gltex->border_color.v[0] = border_color[0];
2572 gltex->border_color.v[1] = border_color[1];
2573 gltex->border_color.v[2] = border_color[2];
2574 gltex->border_color.v[3] = border_color[3];
2577 int xsize = gltex->xsize;
2578 int ysize = gltex->ysize;
2580 for (
int level = 0; level < gltex->num_levels; ++level) {
2584 case Texture::F_rgb:
2585 case Texture::F_rgb5:
2586 case Texture::F_rgb8:
2587 case Texture::F_rgb12:
2588 case Texture::F_rgb332:
2589 copy_rgb_image(dest, xsize, ysize, gtc, level);
2592 case Texture::F_rgba:
2593 case Texture::F_rgbm:
2594 case Texture::F_rgba4:
2595 case Texture::F_rgba5:
2596 case Texture::F_rgba8:
2597 case Texture::F_rgba12:
2598 case Texture::F_rgba16:
2599 case Texture::F_rgba32:
2600 copy_rgba_image(dest, xsize, ysize, gtc, level);
2603 case Texture::F_luminance:
2604 copy_lum_image(dest, xsize, ysize, gtc, level);
2607 case Texture::F_red:
2608 copy_one_channel_image(dest, xsize, ysize, gtc, level, 0);
2611 case Texture::F_green:
2612 copy_one_channel_image(dest, xsize, ysize, gtc, level, 1);
2615 case Texture::F_blue:
2616 copy_one_channel_image(dest, xsize, ysize, gtc, level, 2);
2619 case Texture::F_alpha:
2620 copy_alpha_image(dest, xsize, ysize, gtc, level);
2623 case Texture::F_luminance_alphamask:
2624 case Texture::F_luminance_alpha:
2625 copy_la_image(dest, xsize, ysize, gtc, level);
2629 tinydisplay_cat.error()
2630 <<
"Unsupported texture format "
2635 bytecount += xsize * ysize * 4;
2636 xsize = max(xsize >> 1, 1);
2637 ysize = max(ysize >> 1, 1);
2658 bool TinyGraphicsStateGuardian::
2662 nassertr(tex != (
Texture *)NULL,
false);
2665 if (image_ptr == (
const unsigned char *)NULL) {
2674 _data_transferred_pcollector.add_level(image_size);
2678 if (tinydisplay_cat.is_debug()) {
2679 tinydisplay_cat.debug()
2680 <<
"loading simple image for " << tex->get_name() <<
"\n";
2683 if (!setup_gltex(gltex, width, height, 1)) {
2688 gltex->border_color.v[0] = border_color[0];
2689 gltex->border_color.v[1] = border_color[1];
2690 gltex->border_color.v[2] = border_color[2];
2691 gltex->border_color.v[3] = border_color[3];
2694 memcpy(dest->pixmap, image_ptr, image_size);
2709 bool TinyGraphicsStateGuardian::
2710 setup_gltex(
GLTexture *gltex,
int x_size,
int y_size,
int num_levels) {
2711 int s_bits = get_tex_shift(x_size);
2712 int t_bits = get_tex_shift(y_size);
2714 if (s_bits < 0 || t_bits < 0) {
2715 tinydisplay_cat.error()
2716 <<
"Texture size " << x_size <<
'x' << y_size
2717 <<
" unsupported: dimensions must be power of two"
2718 <<
" and smaller than " << _max_texture_dimension <<
'\n';
2722 num_levels = min(num_levels, MAX_MIPMAP_LEVELS);
2724 gltex->xsize = x_size;
2725 gltex->ysize = y_size;
2727 gltex->s_max = 1 << (s_bits + ZB_POINT_ST_FRAC_BITS);
2728 gltex->t_max = 1 << (t_bits + ZB_POINT_ST_FRAC_BITS);
2730 gltex->num_levels = num_levels;
2736 int total_bytecount = 0;
2742 for (
int level = 0; level < num_levels; ++level) {
2743 int bytecount = x * y * 4;
2744 total_bytecount += bytecount;
2745 x = max((x >> 1), 1);
2746 y = max((y >> 1), 1);
2750 if (gltex->total_bytecount != total_bytecount) {
2751 if (gltex->allocated_buffer != NULL) {
2752 PANDA_FREE_ARRAY(gltex->allocated_buffer);
2753 TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
2755 gltex->allocated_buffer = PANDA_MALLOC_ARRAY(total_bytecount);
2756 gltex->total_bytecount = total_bytecount;
2757 TinyTextureContext::get_class_type().inc_memory_usage(TypeHandle::MC_array, total_bytecount);
2760 char *next_buffer = (
char *)gltex->allocated_buffer;
2761 char *end_of_buffer = next_buffer + total_bytecount;
2765 while (level < num_levels) {
2766 dest = &gltex->levels[level];
2767 int bytecount = x_size * y_size * 4;
2768 dest->pixmap = (PIXEL *)next_buffer;
2769 next_buffer += bytecount;
2770 nassertr(next_buffer <= end_of_buffer,
false);
2772 dest->s_mask = ((1 << (s_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
2773 dest->t_mask = ((1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
2774 dest->s_shift = (ZB_POINT_ST_FRAC_BITS + level);
2775 dest->t_shift = (ZB_POINT_ST_FRAC_BITS - s_bits + level);
2777 x_size = max((x_size >> 1), 1);
2778 y_size = max((y_size >> 1), 1);
2779 s_bits = max(s_bits - 1, 0);
2780 t_bits = max(t_bits - 1, 0);
2788 while (level < MAX_MIPMAP_LEVELS) {
2789 gltex->levels[level] = *dest;
2803 int TinyGraphicsStateGuardian::
2804 get_tex_shift(
int orig_size) {
2805 if ((orig_size & (orig_size - 1)) != 0) {
2809 if (orig_size > _max_texture_dimension) {
2813 return count_bits_in_word((
unsigned int)orig_size - 1);
2822 void TinyGraphicsStateGuardian::
2830 nassertv(!src_image.is_null());
2831 const unsigned char *src = src_image.p();
2833 src += view_size * gtc->
get_view();
2837 #ifdef WORDS_BIGENDIAN
2839 static const int co = 0;
2845 unsigned int *dpix = (
unsigned int *)dest->pixmap;
2846 nassertv(dpix != NULL);
2847 const unsigned char *spix = src;
2848 int pixel_count = xsize * ysize;
2849 while (pixel_count-- > 0) {
2850 *dpix = RGBA8_TO_PIXEL(spix[co], spix[co], spix[co], 0xff);
2862 void TinyGraphicsStateGuardian::
2868 nassertv(!src_image.is_null());
2869 const unsigned char *src = src_image.p();
2871 src += view_size * gtc->
get_view();
2875 #ifdef WORDS_BIGENDIAN
2877 static const int co = 0;
2883 unsigned int *dpix = (
unsigned int *)dest->pixmap;
2884 nassertv(dpix != NULL);
2885 const unsigned char *spix = src;
2886 int pixel_count = xsize * ysize;
2887 while (pixel_count-- > 0) {
2888 *dpix = RGBA8_TO_PIXEL(0xff, 0xff, 0xff, spix[co]);
2901 void TinyGraphicsStateGuardian::
2907 nassertv(!src_image.is_null());
2908 const unsigned char *src = src_image.p();
2910 src += view_size * gtc->
get_view();
2914 #ifdef WORDS_BIGENDIAN
2916 static const int co = 0;
2922 unsigned int *dpix = (
unsigned int *)dest->pixmap;
2923 nassertv(dpix != NULL);
2924 const unsigned char *spix = src;
2925 int pixel_count = xsize * ysize;
2929 while (pixel_count-- > 0) {
2930 *dpix = RGBA8_TO_PIXEL(spix[co], 0, 0, 0xff);
2937 while (pixel_count-- > 0) {
2938 *dpix = RGBA8_TO_PIXEL(0, spix[co], 0, 0xff);
2945 while (pixel_count-- > 0) {
2946 *dpix = RGBA8_TO_PIXEL(0, 0, spix[co], 0xff);
2953 while (pixel_count-- > 0) {
2954 *dpix = RGBA8_TO_PIXEL(0, 0, 0, spix[co]);
2969 void TinyGraphicsStateGuardian::
2975 nassertv(!src_image.is_null());
2976 const unsigned char *src = src_image.p();
2978 src += view_size * gtc->
get_view();
2982 #ifdef WORDS_BIGENDIAN
2984 static const int co = 0;
2990 unsigned int *dpix = (
unsigned int *)dest->pixmap;
2991 nassertv(dpix != NULL);
2992 const unsigned char *spix = src;
2993 int pixel_count = xsize * ysize;
2995 while (pixel_count-- > 0) {
2996 *dpix = RGBA8_TO_PIXEL(spix[co], spix[co], spix[co], spix[cw + co]);
3008 void TinyGraphicsStateGuardian::
3014 nassertv(!src_image.is_null());
3015 const unsigned char *src = src_image.p();
3017 src += view_size * gtc->
get_view();
3021 #ifdef WORDS_BIGENDIAN
3023 static const int co = 0;
3029 unsigned int *dpix = (
unsigned int *)dest->pixmap;
3030 nassertv(dpix != NULL);
3031 const unsigned char *spix = src;
3032 int pixel_count = xsize * ysize;
3034 while (pixel_count-- > 0) {
3035 *dpix = RGBA8_TO_PIXEL(spix[cw + cw + co], spix[cw + co], spix[co], 0xff);
3047 void TinyGraphicsStateGuardian::
3053 nassertv(!src_image.is_null());
3054 const unsigned char *src = src_image.p();
3056 src += view_size * gtc->
get_view();
3060 #ifdef WORDS_BIGENDIAN
3062 static const int co = 0;
3068 unsigned int *dpix = (
unsigned int *)dest->pixmap;
3069 nassertv(dpix != NULL);
3070 const unsigned char *spix = src;
3071 int pixel_count = xsize * ysize;
3073 while (pixel_count-- > 0) {
3074 *dpix = RGBA8_TO_PIXEL(spix[cw + cw + co], spix[cw + co], spix[co], spix[cw + cw + cw + co]);
3086 void TinyGraphicsStateGuardian::
3089 gl_material->specular.v[0] = specular[0];
3090 gl_material->specular.v[1] = specular[1];
3091 gl_material->specular.v[2] = specular[2];
3092 gl_material->specular.v[3] = specular[3];
3095 gl_material->emission.v[0] = emission[0];
3096 gl_material->emission.v[1] = emission[1];
3097 gl_material->emission.v[2] = emission[2];
3098 gl_material->emission.v[3] = emission[3];
3101 gl_material->shininess_i = (int)((material->
get_shininess() / 128.0f) * SPECULAR_BUFFER_RESOLUTION);
3103 _color_material_flags = CMF_ambient | CMF_diffuse;
3107 gl_material->ambient.v[0] = ambient[0];
3108 gl_material->ambient.v[1] = ambient[1];
3109 gl_material->ambient.v[2] = ambient[2];
3110 gl_material->ambient.v[3] = ambient[3];
3112 _color_material_flags &= ~CMF_ambient;
3117 gl_material->diffuse.v[0] = diffuse[0];
3118 gl_material->diffuse.v[1] = diffuse[1];
3119 gl_material->diffuse.v[2] = diffuse[2];
3120 gl_material->diffuse.v[3] = diffuse[3];
3122 _color_material_flags &= ~CMF_diffuse;
3132 void TinyGraphicsStateGuardian::
3133 do_auto_rescale_normal() {
3134 if (_internal_transform->has_uniform_scale()) {
3136 _c->normalize_enabled =
false;
3137 _c->normal_scale = _internal_transform->get_uniform_scale();
3141 _c->normalize_enabled =
true;
3142 _c->normal_scale = 1.0f;
3153 void TinyGraphicsStateGuardian::
3154 load_matrix(
M4 *matrix,
const TransformState *transform) {
3155 const LMatrix4 &pm = transform->get_mat();
3156 for (
int i = 0; i < 4; ++i) {
3157 matrix->m[0][i] = pm.
get_cell(i, 0);
3158 matrix->m[1][i] = pm.
get_cell(i, 1);
3159 matrix->m[2][i] = pm.
get_cell(i, 2);
3160 matrix->m[3][i] = pm.
get_cell(i, 3);
3171 int TinyGraphicsStateGuardian::
3172 get_color_blend_op(ColorBlendAttrib::Operand operand) {
3174 case ColorBlendAttrib::O_zero:
3176 case ColorBlendAttrib::O_one:
3178 case ColorBlendAttrib::O_incoming_color:
3180 case ColorBlendAttrib::O_one_minus_incoming_color:
3182 case ColorBlendAttrib::O_fbuffer_color:
3184 case ColorBlendAttrib::O_one_minus_fbuffer_color:
3186 case ColorBlendAttrib::O_incoming_alpha:
3188 case ColorBlendAttrib::O_one_minus_incoming_alpha:
3190 case ColorBlendAttrib::O_fbuffer_alpha:
3192 case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
3194 case ColorBlendAttrib::O_constant_color:
3196 case ColorBlendAttrib::O_one_minus_constant_color:
3198 case ColorBlendAttrib::O_constant_alpha:
3200 case ColorBlendAttrib::O_one_minus_constant_alpha:
3203 case ColorBlendAttrib::O_incoming_color_saturate:
3206 case ColorBlendAttrib::O_color_scale:
3208 case ColorBlendAttrib::O_one_minus_color_scale:
3210 case ColorBlendAttrib::O_alpha_scale:
3212 case ColorBlendAttrib::O_one_minus_alpha_scale:
3224 ZB_lookupTextureFunc TinyGraphicsStateGuardian::
3225 get_tex_filter_func(SamplerState::FilterType filter) {
3227 case SamplerState::FT_nearest:
3228 return &lookup_texture_nearest;
3230 case SamplerState::FT_linear:
3231 return &lookup_texture_bilinear;
3233 case SamplerState::FT_nearest_mipmap_nearest:
3234 return &lookup_texture_mipmap_nearest;
3236 case SamplerState::FT_nearest_mipmap_linear:
3237 return &lookup_texture_mipmap_linear;
3239 case SamplerState::FT_linear_mipmap_nearest:
3240 return &lookup_texture_mipmap_bilinear;
3242 case SamplerState::FT_linear_mipmap_linear:
3243 return &lookup_texture_mipmap_trilinear;
3246 return &lookup_texture_nearest;
3256 ZB_texWrapFunc TinyGraphicsStateGuardian::
3257 get_tex_wrap_func(SamplerState::WrapMode wrap_mode) {
3258 switch (wrap_mode) {
3259 case SamplerState::WM_clamp:
3260 case SamplerState::WM_border_color:
3261 return &texcoord_clamp;
3263 case SamplerState::WM_repeat:
3264 case SamplerState::WM_invalid:
3265 return &texcoord_repeat;
3267 case SamplerState::WM_mirror:
3268 return &texcoord_mirror;
3270 case SamplerState::WM_mirror_once:
3271 return &texcoord_mirror_once;
3274 return &texcoord_repeat;
3283 void TinyGraphicsStateGuardian::
3284 texgen_null(
V2 &result, TinyGraphicsStateGuardian::TexCoordData &) {
3295 void TinyGraphicsStateGuardian::
3296 texgen_simple(
V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
3298 const LVecBase2 &d = tcdata._r1.get_data2();
3309 void TinyGraphicsStateGuardian::
3310 texgen_texmat(
V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
3312 LVecBase4 d = tcdata._r1.get_data4() * tcdata._mat;
3313 result.v[0] = d[0] / d[3];
3314 result.v[1] = d[1] / d[3];
3323 void TinyGraphicsStateGuardian::
3324 texgen_sphere_map(
V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
3326 LVector3 n = tcdata._mat.xform_vec(tcdata._r1.get_data3());
3327 LVector3 u = tcdata._mat.xform_point(tcdata._r2.get_data3());
3334 LVector3 r = u - n * dot(n, u) * 2.0f;
3337 PN_stdfloat m = 2.0f * csqrt(r[0] * r[0] + r[1] * r[1] + (r[2] + 1.0f) * (r[2] + 1.0f));
3340 result.v[0] = r[0] / m + 0.5f;
3341 result.v[1] = r[1] / m + 0.5f;
Format get_format() const
Returns the format of the texture, which represents both the semantic meaning of the texels and...
A light shining from infinitely far away in a particular direction, like sunlight.
virtual bool draw_points(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected points.
Mode get_mode() const
Returns the colorBlend mode.
virtual Light * as_light()
Cross-casts the node to a Light pointer, if it is one of the four kinds of Light nodes, or returns NULL if it is not.
FilterType get_effective_magfilter() const
Returns the filter mode of the texture for magnification, with special treatment for FT_default...
The abstract interface to all kinds of lights.
virtual void end_frame(Thread *current_thread)
Called after each frame is rendered, to allow the GSG a chance to do any internal cleanup after rende...
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
virtual void end_draw_primitives()
Called after a sequence of draw_primitive() functions are called, this should do whatever cleanup is ...
This is the base class for all three-component vectors and points.
Mode get_mode() const
Return the mode of this stage.
int get_simple_x_size() const
Returns the width of the "simple" image in texels.
virtual bool update_texture(TextureContext *tc, bool force)
Ensures that the current Texture data is refreshed onto the GSG.
void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const
Similar to get_region_pixels(), but returns the upper left corner, and the pixel numbers are numbered...
void setup_2d_texture()
Sets the texture as an empty 2-d texture with no dimensions.
const LColor & get_ambient() const
Returns the ambient color setting, if it has been set.
This is a base class for GraphicsWindow (actually, GraphicsOutput) and DisplayRegion, both of which are conceptually rectangular regions into which drawing commands may be issued.
Enables or disables writing to the depth buffer.
virtual void do_issue_light()
This implementation of do_issue_light() assumes we have a limited number of hardware lights available...
static LMatrix4f scale_mat(const LVecBase3f &scale)
Returns a matrix that applies the indicated scale in each of the three axes.
virtual bool depth_offset_decals()
Returns true if this GSG can implement decals using a DepthOffsetAttrib, or false if that is unreliab...
A base class for any number of different kinds of lenses, linear and otherwise.
bool has_ambient() const
Returns true if the ambient color has been explicitly set for this material, false otherwise...
Enables or disables writing to the color buffer.
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a "scene" ...
bool is_off() const
Returns true if the MaterialAttrib is an 'off' MaterialAttrib, indicating that it should disable the ...
Indicates which, if any, material should be applied to geometry.
Enables or disables writing to the depth buffer.
virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected triangles.
size_t get_ram_image_size() const
Returns the total number of bytes used by the in-memory image, across all pages and views...
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
This is a convenience class to specialize ConfigVariable as a boolean type.
ComponentType get_component_type() const
Returns the numeric interpretation of each component of the texture.
virtual void end_draw_primitives()
Called after a sequence of draw_primitive() functions are called, this should do whatever cleanup is ...
const LPoint3 & get_point() const
Returns the point in space at which the light is located.
virtual bool framebuffer_copy_to_ram(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)
Copy the pixels within the indicated display region from the framebuffer into system memory...
This controls the enabling of transparency.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
CPTA_uchar get_uncompressed_ram_image()
Returns the system-RAM image associated with the texture, in an uncompressed form if at all possible...
const LVector3 & get_view_vector() const
Returns the axis along which the lens is facing.
WrapMode get_wrap_v() const
Returns the wrap mode of the texture in the V direction.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
unsigned int get_channels() const
Returns the mask of color channels that are enabled by this attrib.
void setup_texture(TextureType texture_type, int x_size, int y_size, int z_size, ComponentType component_type, Format format)
Sets the texture to the indicated type and dimensions, presumably in preparation for calling read() o...
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
Specifies whether flat shading (per-polygon) or smooth shading (per-vertex) is in effect...
This is a special class object that holds all the information returned by a particular GSG to indicat...
PandaCompareFunc get_mode() const
Returns the depth write mode.
virtual void end_frame(Thread *current_thread)
Called after each frame is rendered, to allow the GSG a chance to do any internal cleanup after rende...
Material * get_material() const
If the MaterialAttrib is not an 'off' MaterialAttrib, returns the material that is associated...
const LVecBase4 & get_data4()
Returns the data associated with the read row, expressed as a 4-component value, and advances the rea...
PandaNode * node() const
Returns the referenced node of the path.
FilterType get_magfilter() const
Returns the filter mode of the texture for magnification.
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
bool uses_mipmaps() const
Returns true if the minfilter settings on this sampler indicate the use of mipmapping, false otherwise.
static bool is_mipmap(FilterType type)
Returns true if the indicated filter type requires the use of mipmaps, or false if it does not...
A lightweight class that can be used to automatically start and stop a PStatCollector around a sectio...
virtual bool prepare_lens()
Makes the current lens (whichever lens was most recently specified with set_scene()) active...
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Texture * get_texture() const
Returns the pointer to the associated Texture object.
virtual void close_gsg()
This is called by the associated GraphicsWindow when close_window() is called.
PN_stdfloat get_shininess() const
Returns the shininess exponent of the material.
Mode get_mode(TextureStage *stage) const
Returns the generation mode associated with the named texture stage, or M_off if nothing is associate...
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
void do_issue_color()
This method is defined in the base class because it is likely that this functionality will be used fo...
static const LMatrix4f & convert_mat(CoordinateSystem from, CoordinateSystem to)
Returns a matrix that transforms from the indicated coordinate system to the indicated coordinate sys...
PN_stdfloat get_exponent() const FINAL
Returns the exponent that controls the amount of light falloff from the center of the spotlight...
const LColor & get_emission() const
Returns the emission color setting, if it has been set.
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping, false otherwise.
void texture_uploaded(Texture *tex)
This method is called by the GraphicsStateGuardian after a texture has been successfully uploaded to ...
PN_stdfloat get_min_value() const
Returns the value for the minimum (closest) depth value to be stored in the buffer, in the range 0
int get_num_ram_mipmap_images() const
Returns the maximum number of mipmap level images available in system memory.
void dequeue_lru()
Removes the page from its AdaptiveLru.
int get_expected_mipmap_x_size(int n) const
Returns the x_size that the nth mipmap level should have, based on the texture's size.
PN_stdfloat get_hfov() const
Returns the horizontal component of fov only.
const LColor & get_specular_color() const FINAL
Returns the color of specular highlights generated by the light.
void enqueue_lru(AdaptiveLru *lru)
Adds the page to the LRU for the first time, or marks it recently-accessed if it has already been add...
Indicates which faces should be culled based on their vertex ordering.
This specialization on GeomMunger finesses vertices for TinyPanda rendering.
bool was_simple_image_modified() const
Returns true if the texture's "simple" image has been modified since the last time mark_simple_loaded...
Mode get_mode() const
Returns the depth write mode.
InternalName * get_texcoord_name() const
See set_texcoord_name.
A lightweight class that represents a single element that may be timed and/or counted via stats...
Mode get_effective_mode() const
Returns the effective culling mode.
Mode get_mode() const
Returns the shade mode.
virtual bool framebuffer_copy_to_texture(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)
Copy the pixels within the indicated display region from the framebuffer into texture memory...
PandaCompareFunc get_mode() const
Returns the alpha write mode.
LColor get_color() const
Returns the constant color associated with the attrib.
PN_stdfloat get_reference_alpha() const
Returns the alpha reference value.
virtual void release_texture(TextureContext *tc)
Frees the GL resources previously allocated for the texture.
int get_z_size() const
Returns the depth of the texture image in texels.
This is a 4-by-4 transform matrix.
int get_num_components() const
Returns the number of color components for each texel of the texture image.
const LVector3 & get_direction() const
Returns the direction in which the light is aimed.
FilterType get_minfilter() const
Returns the filter mode of the texture for minification.
virtual PreparedGraphicsObjects * get_prepared_objects()
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
int get_current_tex_view_offset() const
Returns the current tex view offset, as set by the last call to prepare_display_region().
An object to create GraphicsOutputs that share a particular 3-D API.
const LColor & get_specular_color() const FINAL
Returns the color of specular highlights generated by the light.
CPTA_uchar get_simple_ram_image() const
Returns the image data associated with the "simple" texture image.
const LVecBase3 & get_data3()
Returns the data associated with the read row, expressed as a 3-component value, and advances the rea...
virtual void free_pointers()
Frees some memory that was explicitly allocated within the glgsg.
bool has_column() const
Returns true if a valid data type has been successfully set, or false if the data type does not exist...
A light originating from a single point in space, and shining in a particular direction, with a cone-shaped falloff.
This is the base class for all two-component vectors and points.
const LColor & get_specular() const
Returns the specular color setting, if it has been set.
CPTA_uchar get_ram_mipmap_image(int n) const
Returns the system-RAM image data associated with the nth mipmap level, if present.
virtual void bind_light(PointLight *light_obj, const NodePath &light, int light_id)
Called the first time a particular light has been bound to a given id within a frame, this should set up the associated hardware light with the light's properties.
WrapMode get_wrap_u() const
Returns the wrap mode of the texture in the U direction.
LColor get_border_color() const
Returns the solid color of the texture's border.
const LColor & get_specular_color() const FINAL
Returns the color of specular highlights generated by the light.
size_t get_ram_mipmap_view_size(int n) const
Returns the number of bytes used by the in-memory image per view for mipmap level n...
Enables or disables writing of pixel to framebuffer based on its alpha value relative to a reference ...
TextureType get_texture_type() const
Returns the overall interpretation of the texture.
virtual void reset()
Resets all internal state as if the gsg were newly created.
Defines the way an object appears in the presence of lighting.
bool has_simple_ram_image() const
Returns true if the Texture has a "simple" image available in main RAM.
int get_offset() const
Returns the depth offset represented by this attrib.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
Mode get_mode() const
Returns the render mode.
int get_tex_view_offset() const
Returns the current setting of the tex_view_offset.
const LVecBase3 & get_attenuation() const FINAL
Returns the terms of the attenuation equation for the light.
static void add_gsg(GraphicsStateGuardianBase *gsg)
Called by a GSG after it has been initialized, to add a new GSG to the available list.
Represents a set of settings that indicate how a texture is sampled.
TextureContext * prepare_now(int view, PreparedGraphicsObjects *prepared_objects, GraphicsStateGuardianBase *gsg)
Creates a context for the texture on the particular GSG, if it does not already exist.
float get_cell(int row, int col) const
Returns a particular element of the matrix.
This is the base class for all three-component vectors and points.
virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomMunger *munger, const GeomVertexDataPipelineReader *data_reader, bool force)
Called before a sequence of draw_primitive() functions are called, this should prepare the vertex dat...
Applies a transform matrix to UV's before they are rendered.
bool is_null() const
Returns true if the PointerTo is a NULL pointer, false otherwise.
bool has_diffuse() const
Returns true if the diffuse color has been explicitly set for this material, false otherwise...
Mode get_mode() const
Returns the transparency mode.
Mode get_mode() const
Returns the render mode.
This specifies how colors are blended into the frame buffer, for special effects. ...
void generate_ram_mipmap_images()
Automatically fills in the n mipmap levels of the Texture, based on the texture's source image...
PN_stdfloat get_max_value() const
Returns the value for the maximum (farthest) depth value to be stored in the buffer, in the range 0
A thread; that is, a lightweight process.
bool was_image_modified() const
Returns true if the texture image has been modified since the last time mark_loaded() was called...
void update_data_size_bytes(size_t new_data_size_bytes)
Should be called (usually by a derived class) when the on-card size of this object has changed...
This object provides a high-level interface for quickly reading a sequence of numeric values from a v...
int get_expected_mipmap_y_size(int n) const
Returns the y_size that the nth mipmap level should have, based on the texture's size.
This is a special kind of attribute that instructs the graphics driver to apply an offset or bias to ...
void mark_loaded()
Should be called after the texture has been loaded into graphics memory, this updates the internal fl...
Encapsulates all the communication with a particular instance of a given rendering backend...
Specifies how polygons are to be drawn.
int get_view() const
Returns the specific view of a multiview texture this context represents.
void set_active(bool flag)
Changes the active flag associated with this object.
size_t get_simple_ram_image_size() const
Returns the number of bytes used by the "simple" image, or 0 if there is no simple image...
bool is_empty() const
Returns true if the NodePath contains no nodes.
FilterType get_effective_minfilter() const
Returns the filter mode of the texture for minification, with special treatment for FT_default...
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a "scene" (usual...
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a "scene" (usual...
bool has_ram_image() const
Returns true if the Texture has its image contents available in main RAM, false if it exists only in ...
Specifies how polygons are to be drawn.
virtual TextureContext * prepare_texture(Texture *tex, int view)
Creates whatever structures the GSG requires to represent the texture internally, and returns a newly...
A rectangular subregion within a window for rendering into.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
const LVecBase3 & get_attenuation() const FINAL
Returns the terms of the attenuation equation for the light.
virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomMunger *munger, const GeomVertexDataPipelineReader *data_reader, bool force)
Called before a sequence of draw_primitive() functions are called, this should prepare the vertex dat...
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
void set_row_unsafe(int row)
Sets the start row to the indicated value, without internal checks.
This restricts rendering to within a rectangular region of the scene, without otherwise affecting the...
int get_simple_y_size() const
Returns the height of the "simple" image in texels.
int get_component_width() const
Returns the number of bytes stored for each color component of a texel.
This class is the main interface to controlling the render process.
This is a two-component point in space.
Operand get_operand_b() const
Returns the multiplier for the second component.
virtual void reset()
Resets all internal state as if the gsg were newly created.
virtual bool begin_frame(Thread *current_thread)
Called before each frame is rendered, to allow the GSG a chance to do any internal cleanup before beg...
TypeHandle is the identifier used to differentiate C++ class types.
int get_expected_num_mipmap_levels() const
Returns the number of mipmap levels that should be defined for this texture, given the texture's size...
PTA_uchar modify_ram_image()
Returns a modifiable pointer to the system-RAM image.
virtual void set_state_and_transform(const RenderState *state, const TransformState *transform)
Simultaneously resets the render state and the transform state.
const LVecBase4 & get_frame() const
Returns the left, right, bottom, top coordinates of the scissor frame.
void mark_simple_loaded()
Should be called after the texture's "simple" image has been loaded into graphics memory...
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
bool normalize()
Normalizes the vector in place.
virtual bool begin_frame(Thread *current_thread)
Called before each frame is rendered, to allow the GSG a chance to do any internal cleanup before beg...
Defines the properties of a named stage of the multitexture pipeline.
Computes texture coordinates for geometry automatically based on vertex position and/or normal...
const LColor & get_diffuse() const
Returns the diffuse color setting, if it has been set.
virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle strips.
LPoint3 get_nodal_point() const
Returns the center point of the lens: the point from which the lens is viewing.
size_t get_expected_ram_page_size() const
Returns the number of bytes that should be used per each Z page of the 3-d texture.
int get_y_size() const
Returns the height of the texture image in texels.
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer, etc.) of a drawing region.
bool might_have_ram_image() const
Returns true if the texture's image contents are currently available in main RAM, or there is reason ...
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
An interface to the TinyPanda software rendering code within this module.
Operand get_operand_a() const
Returns the multiplier for the first component.
A light originating from a single point in space, and shining in all directions.
int get_x_size() const
Returns the width of the texture image in texels.
void get_region_pixels_i(int &xo, int &yo, int &w, int &h) const
Similar to get_region_pixels(), but returns the upper left corner, and the pixel numbers are numbered...
QualityLevel get_quality_level() const
Returns the current quality_level hint.
Similar to PointerToArray, except that its contents may not be modified.
Indicates which set of lights should be considered "on" to illuminate geometry at this level and belo...
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a "scene" ...
static const LVecBase4f & zero()
Returns a zero-length vector.
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Prepare a display region for rendering (set up scissor region and viewport)
Lens * get_lens(int index=0) const
Returns a pointer to the particular Lens associated with this LensNode, or NULL if there is not yet a...
virtual bool draw_lines(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected line segments.