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);
233 bool clear_color =
false;
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;
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);
323 CPT(TransformState) TinyGraphicsStateGuardian::
324 calc_projection_mat(
const Lens *lens) {
325 if (lens == (
Lens *)NULL) {
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);
1803 _texturing_state = 0;
1818 LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
1820 int num_enabled = 0;
1821 int num_on_lights = 0;
1823 const LightAttrib *target_light = DCAST(
LightAttrib, _target_rs->get_attrib_def(LightAttrib::get_class_slot()));
1824 if (display_cat.is_spam()) {
1826 <<
"do_issue_light: " << target_light <<
"\n";
1830 clear_light_state();
1834 CPT(
LightAttrib) new_light = target_light->filter_to_max(_max_lights);
1835 if (display_cat.is_spam()) {
1836 new_light->write(display_cat.spam(
false), 2);
1839 num_on_lights = new_light->get_num_on_lights();
1840 for (
int li = 0; li < num_on_lights; li++) {
1841 NodePath light = new_light->get_on_light(li);
1844 nassertv(light_obj != (
Light *)NULL);
1846 _lighting_enabled =
true;
1847 _c->lighting_enabled =
true;
1849 if (light_obj->get_type() == AmbientLight::get_class_type()) {
1851 cur_ambient_light += light_obj->get_color();
1855 light_obj->bind(
this, light, num_enabled);
1860 GLLight *gl_light = _c->first_light;
1861 nassertv(gl_light != NULL);
1862 const LColor &diffuse = light_obj->get_color();
1863 gl_light->diffuse.v[0] = diffuse[0];
1864 gl_light->diffuse.v[1] = diffuse[1];
1865 gl_light->diffuse.v[2] = diffuse[2];
1866 gl_light->diffuse.v[3] = diffuse[3];
1871 _c->ambient_light_model.v[0] = cur_ambient_light[0];
1872 _c->ambient_light_model.v[1] = cur_ambient_light[1];
1873 _c->ambient_light_model.v[2] = cur_ambient_light[2];
1874 _c->ambient_light_model.v[3] = cur_ambient_light[3];
1878 _transform_stale =
true;
1891 pair<Lights::iterator, bool> lookup = _plights.insert(Lights::value_type(light,
GLLight()));
1892 GLLight *gl_light = &(*lookup.first).second;
1893 if (lookup.second) {
1895 memset(gl_light, 0,
sizeof(
GLLight));
1898 gl_light->specular.v[0] = specular[0];
1899 gl_light->specular.v[1] = specular[1];
1900 gl_light->specular.v[2] = specular[2];
1901 gl_light->specular.v[3] = specular[3];
1905 CPT(TransformState) render_transform =
1906 _cs_transform->compose(_scene_setup->get_world_transform());
1908 CPT(TransformState) transform = light.
get_transform(_scene_setup->get_scene_root().get_parent());
1909 CPT(TransformState) net_transform = render_transform->compose(transform);
1912 gl_light->position.v[0] = pos[0];
1913 gl_light->position.v[1] = pos[1];
1914 gl_light->position.v[2] = pos[2];
1915 gl_light->position.v[3] = 1.0f;
1918 gl_light->spot_exponent = 0.0f;
1921 gl_light->spot_cutoff = 180.0f;
1924 gl_light->attenuation[0] = att[0];
1925 gl_light->attenuation[1] = att[1];
1926 gl_light->attenuation[2] = att[2];
1929 nassertv(gl_light->next == NULL);
1932 gl_light->next = _c->first_light;
1933 _c->first_light = gl_light;
1946 pair<Lights::iterator, bool> lookup = _dlights.insert(Lights::value_type(light,
GLLight()));
1947 GLLight *gl_light = &(*lookup.first).second;
1948 if (lookup.second) {
1950 memset(gl_light, 0,
sizeof(
GLLight));
1953 gl_light->specular.v[0] = specular[0];
1954 gl_light->specular.v[1] = specular[1];
1955 gl_light->specular.v[2] = specular[2];
1956 gl_light->specular.v[3] = specular[3];
1960 CPT(TransformState) render_transform =
1961 _cs_transform->compose(_scene_setup->get_world_transform());
1963 CPT(TransformState) transform = light.
get_transform(_scene_setup->get_scene_root().get_parent());
1964 CPT(TransformState) net_transform = render_transform->compose(transform);
1968 gl_light->position.v[0] = -dir[0];
1969 gl_light->position.v[1] = -dir[1];
1970 gl_light->position.v[2] = -dir[2];
1971 gl_light->position.v[3] = 0.0f;
1973 gl_light->norm_position.v[0] = -dir[0];
1974 gl_light->norm_position.v[1] = -dir[1];
1975 gl_light->norm_position.v[2] = -dir[2];
1976 gl_V3_Norm(&gl_light->norm_position);
1979 gl_light->spot_exponent = 0.0f;
1982 gl_light->spot_cutoff = 180.0f;
1986 gl_light->attenuation[0] = 1.0f;
1987 gl_light->attenuation[1] = 0.0f;
1988 gl_light->attenuation[2] = 0.0f;
1991 nassertv(gl_light->next == NULL);
1994 gl_light->next = _c->first_light;
1995 _c->first_light = gl_light;
2008 pair<Lights::iterator, bool> lookup = _plights.insert(Lights::value_type(light,
GLLight()));
2009 GLLight *gl_light = &(*lookup.first).second;
2010 if (lookup.second) {
2012 memset(gl_light, 0,
sizeof(
GLLight));
2015 gl_light->specular.v[0] = specular[0];
2016 gl_light->specular.v[1] = specular[1];
2017 gl_light->specular.v[2] = specular[2];
2018 gl_light->specular.v[3] = specular[3];
2021 nassertv(lens != (
Lens *)NULL);
2025 CPT(TransformState) render_transform =
2026 _cs_transform->compose(_scene_setup->get_world_transform());
2028 CPT(TransformState) transform = light.
get_transform(_scene_setup->get_scene_root().get_parent());
2029 CPT(TransformState) net_transform = render_transform->compose(transform);
2031 const LMatrix4 &light_mat = net_transform->get_mat();
2036 gl_light->position.v[0] = pos[0];
2037 gl_light->position.v[1] = pos[1];
2038 gl_light->position.v[2] = pos[2];
2039 gl_light->position.v[3] = 1.0f;
2041 gl_light->spot_direction.v[0] = dir[0];
2042 gl_light->spot_direction.v[1] = dir[1];
2043 gl_light->spot_direction.v[2] = dir[2];
2045 gl_light->norm_spot_direction.v[0] = dir[0];
2046 gl_light->norm_spot_direction.v[1] = dir[1];
2047 gl_light->norm_spot_direction.v[2] = dir[2];
2048 gl_V3_Norm(&gl_light->norm_spot_direction);
2051 gl_light->spot_cutoff = lens->
get_hfov() * 0.5f;
2054 gl_light->attenuation[0] = att[0];
2055 gl_light->attenuation[1] = att[1];
2056 gl_light->attenuation[2] = att[2];
2059 nassertv(gl_light->next == NULL);
2062 gl_light->next = _c->first_light;
2063 _c->first_light = gl_light;
2075 void TinyGraphicsStateGuardian::
2076 do_issue_transform() {
2077 _transform_state_pcollector.add_level(1);
2078 _transform_stale =
true;
2080 if (_auto_rescale_normal) {
2081 do_auto_rescale_normal();
2090 void TinyGraphicsStateGuardian::
2091 do_issue_render_mode() {
2094 _filled_flat =
false;
2096 switch (target_render_mode->
get_mode()) {
2097 case RenderModeAttrib::M_unchanged:
2098 case RenderModeAttrib::M_filled:
2099 _c->draw_triangle_front = gl_draw_triangle_fill;
2100 _c->draw_triangle_back = gl_draw_triangle_fill;
2103 case RenderModeAttrib::M_filled_flat:
2104 _c->draw_triangle_front = gl_draw_triangle_fill;
2105 _c->draw_triangle_back = gl_draw_triangle_fill;
2106 _filled_flat =
true;
2109 case RenderModeAttrib::M_wireframe:
2110 _c->draw_triangle_front = gl_draw_triangle_line;
2111 _c->draw_triangle_back = gl_draw_triangle_line;
2114 case RenderModeAttrib::M_point:
2115 _c->draw_triangle_front = gl_draw_triangle_point;
2116 _c->draw_triangle_back = gl_draw_triangle_point;
2120 tinydisplay_cat.error()
2121 <<
"Unknown render mode " << (int)target_render_mode->
get_mode() << endl;
2130 void TinyGraphicsStateGuardian::
2131 do_issue_rescale_normal() {
2133 RescaleNormalAttrib::Mode mode = target_rescale_normal->
get_mode();
2135 _auto_rescale_normal =
false;
2138 case RescaleNormalAttrib::M_none:
2139 _c->normalize_enabled =
false;
2140 _c->normal_scale = 1.0f;
2143 case RescaleNormalAttrib::M_normalize:
2144 _c->normalize_enabled =
true;
2145 _c->normal_scale = 1.0f;
2148 case RescaleNormalAttrib::M_rescale:
2149 case RescaleNormalAttrib::M_auto:
2150 _auto_rescale_normal =
true;
2151 do_auto_rescale_normal();
2155 tinydisplay_cat.error()
2156 <<
"Unknown rescale_normal mode " << (int)mode << endl;
2165 void TinyGraphicsStateGuardian::
2166 do_issue_depth_offset() {
2168 int offset = target_depth_offset->
get_offset();
2171 PN_stdfloat min_value = target_depth_offset->
get_min_value();
2172 PN_stdfloat max_value = target_depth_offset->
get_max_value();
2173 if (min_value == 0.0f && max_value == 1.0f) {
2174 _c->has_zrange =
false;
2176 _c->has_zrange =
true;
2177 _c->zmin = min_value;
2178 _c->zrange = max_value - min_value;
2187 void TinyGraphicsStateGuardian::
2188 do_issue_cull_face() {
2193 case CullFaceAttrib::M_cull_none:
2194 _c->cull_face_enabled =
false;
2196 case CullFaceAttrib::M_cull_clockwise:
2197 _c->cull_face_enabled =
true;
2198 _c->cull_clockwise =
true;
2200 case CullFaceAttrib::M_cull_counter_clockwise:
2201 _c->cull_face_enabled =
true;
2202 _c->cull_clockwise =
false;
2205 tinydisplay_cat.error()
2206 <<
"invalid cull face mode " << (int)mode << endl;
2216 void TinyGraphicsStateGuardian::
2217 do_issue_material() {
2224 target_material->
is_off()) {
2231 setup_material(&_c->materials[0], material);
2233 if (material->get_twoside()) {
2235 setup_material(&_c->materials[1], material);
2238 _c->local_light_model = material->get_local();
2239 _c->light_model_two_side = material->get_twoside();
2247 void TinyGraphicsStateGuardian::
2248 do_issue_texture() {
2249 _texturing_state = 0;
2250 _c->num_textures_enabled = 0;
2252 int num_stages = _target_texture->get_num_on_ff_stages();
2253 if (num_stages == 0) {
2257 nassertv(num_stages <= MAX_TEXTURE_STAGES);
2259 bool all_replace =
true;
2260 bool all_nearest =
true;
2261 bool all_mipmap_nearest =
true;
2262 bool any_mipmap =
false;
2263 bool needs_general =
false;
2264 Texture::QualityLevel best_quality_level = Texture::QL_default;
2266 for (
int si = 0; si < num_stages; ++si) {
2267 TextureStage *stage = _target_texture->get_on_ff_stage(si);
2268 Texture *texture = _target_texture->get_on_texture(stage);
2269 nassertv(texture != (
Texture *)NULL);
2279 const SamplerState &sampler = _target_texture->get_on_sampler(stage);
2288 if (stage->
get_mode() != TextureStage::M_replace) {
2289 all_replace =
false;
2292 Texture::QualityLevel quality_level = _texture_quality_override;
2293 if (quality_level == Texture::QL_default) {
2296 if (quality_level == Texture::QL_default) {
2297 quality_level = texture_quality_level;
2300 best_quality_level = max(best_quality_level, quality_level);
2302 ZTextureDef *texture_def = &_c->zb->current_textures[si];
2306 SamplerState::FilterType minfilter = sampler.
get_minfilter();
2307 SamplerState::FilterType magfilter = sampler.
get_magfilter();
2311 if (minfilter == SamplerState::FT_nearest_mipmap_nearest) {
2312 minfilter = SamplerState::FT_nearest;
2314 minfilter = SamplerState::FT_linear;
2320 if (quality_level == Texture::QL_fastest) {
2321 minfilter = SamplerState::FT_nearest;
2322 magfilter = SamplerState::FT_nearest;
2324 }
else if (quality_level == Texture::QL_normal) {
2326 minfilter = SamplerState::FT_nearest_mipmap_nearest;
2328 minfilter = SamplerState::FT_nearest;
2330 magfilter = SamplerState::FT_nearest;
2332 }
else if (quality_level == Texture::QL_best) {
2337 texture_def->tex_minfilter_func = get_tex_filter_func(minfilter);
2338 texture_def->tex_magfilter_func = get_tex_filter_func(magfilter);
2340 SamplerState::WrapMode wrap_u = sampler.
get_wrap_u();
2341 SamplerState::WrapMode wrap_v = sampler.
get_wrap_v();
2342 if (td_ignore_clamp) {
2343 wrap_u = SamplerState::WM_repeat;
2344 wrap_v = SamplerState::WM_repeat;
2347 if (wrap_u != SamplerState::WM_repeat || wrap_v != SamplerState::WM_repeat) {
2350 needs_general =
true;
2357 texture_def->tex_minfilter_func_impl = texture_def->tex_minfilter_func;
2358 texture_def->tex_magfilter_func_impl = texture_def->tex_magfilter_func;
2362 texture_def->tex_minfilter_func = apply_wrap_general_minfilter;
2363 texture_def->tex_magfilter_func = apply_wrap_general_magfilter;
2365 texture_def->tex_wrap_u_func = get_tex_wrap_func(wrap_u);
2366 texture_def->tex_wrap_v_func = get_tex_wrap_func(wrap_v);
2370 if (wrap_u && SamplerState::WM_border_color && wrap_v == SamplerState::WM_border_color) {
2371 texture_def->tex_minfilter_func = apply_wrap_border_color_minfilter;
2372 texture_def->tex_magfilter_func = apply_wrap_border_color_magfilter;
2373 }
else if (wrap_u && SamplerState::WM_clamp && wrap_v == SamplerState::WM_clamp) {
2374 texture_def->tex_minfilter_func = apply_wrap_clamp_minfilter;
2375 texture_def->tex_magfilter_func = apply_wrap_clamp_magfilter;
2379 if (minfilter != SamplerState::FT_nearest || magfilter != SamplerState::FT_nearest) {
2380 all_nearest =
false;
2383 if (minfilter != SamplerState::FT_nearest_mipmap_nearest ||
2384 magfilter != SamplerState::FT_nearest) {
2385 all_mipmap_nearest =
false;
2394 _c->num_textures_enabled = num_stages;
2395 _texture_replace = all_replace;
2397 _texturing_state = 2;
2398 if (num_stages >= 3) {
2399 _texturing_state = 4;
2400 }
else if (num_stages == 2) {
2401 _texturing_state = 3;
2402 }
else if (!td_perspective_textures) {
2403 _texturing_state = 1;
2406 if (best_quality_level == Texture::QL_best) {
2408 _texfilter_state = 2;
2410 if (!needs_general) {
2413 _texfilter_state = 0;
2414 }
else if (all_mipmap_nearest) {
2416 _texfilter_state = 1;
2420 }
else if (best_quality_level == Texture::QL_fastest) {
2423 _texfilter_state = 0;
2424 _texturing_state = 1;
2430 _texfilter_state = 0;
2432 _texfilter_state = 1;
2435 if (needs_general) {
2438 _texfilter_state = 2;
2448 void TinyGraphicsStateGuardian::
2449 do_issue_scissor() {
2452 set_scissor(frame[0], frame[1], frame[2], frame[3]);
2461 void TinyGraphicsStateGuardian::
2462 set_scissor(PN_stdfloat left, PN_stdfloat right, PN_stdfloat bottom, PN_stdfloat top) {
2463 _c->scissor.left = left;
2464 _c->scissor.right = right;
2465 _c->scissor.bottom = bottom;
2466 _c->scissor.top = top;
2467 gl_eval_viewport(_c);
2469 PN_stdfloat xsize = right - left;
2470 PN_stdfloat ysize = top - bottom;
2471 PN_stdfloat xcenter = (left + right) - 1.0f;
2472 PN_stdfloat ycenter = (bottom + top) - 1.0f;
2473 if (xsize == 0.0f || ysize == 0.0f) {
2476 _scissor_mat = TransformState::make_identity();
2478 _scissor_mat = TransformState::make_scale(
LVecBase3(1.0f / xsize, 1.0f / ysize, 1.0f))->compose(TransformState::make_pos(
LPoint3(-xcenter, -ycenter, 0.0f)));
2489 bool TinyGraphicsStateGuardian::
2505 bool TinyGraphicsStateGuardian::
2509 if (_effective_incomplete_render && !force) {
2512 !_loader.is_null()) {
2515 async_reload_texture(gtc);
2518 return upload_simple_texture(gtc);
2544 if (tinydisplay_cat.is_debug()) {
2545 tinydisplay_cat.debug()
2546 <<
"loading texture " << tex->get_name() <<
", " 2548 << num_levels <<
", uses_mipmaps = " << uses_mipmaps <<
"\n";
2556 gltex->border_color.v[0] = border_color[0];
2557 gltex->border_color.v[1] = border_color[1];
2558 gltex->border_color.v[2] = border_color[2];
2559 gltex->border_color.v[3] = border_color[3];
2562 int xsize = gltex->xsize;
2563 int ysize = gltex->ysize;
2565 for (
int level = 0; level < gltex->num_levels; ++level) {
2569 case Texture::F_rgb:
2570 case Texture::F_rgb5:
2571 case Texture::F_rgb8:
2572 case Texture::F_rgb12:
2573 case Texture::F_rgb332:
2574 copy_rgb_image(dest, xsize, ysize, gtc, level);
2577 case Texture::F_rgba:
2578 case Texture::F_rgbm:
2579 case Texture::F_rgba4:
2580 case Texture::F_rgba5:
2581 case Texture::F_rgba8:
2582 case Texture::F_rgba12:
2583 case Texture::F_rgba16:
2584 case Texture::F_rgba32:
2585 copy_rgba_image(dest, xsize, ysize, gtc, level);
2588 case Texture::F_luminance:
2589 copy_lum_image(dest, xsize, ysize, gtc, level);
2592 case Texture::F_red:
2593 copy_one_channel_image(dest, xsize, ysize, gtc, level, 0);
2596 case Texture::F_green:
2597 copy_one_channel_image(dest, xsize, ysize, gtc, level, 1);
2600 case Texture::F_blue:
2601 copy_one_channel_image(dest, xsize, ysize, gtc, level, 2);
2604 case Texture::F_alpha:
2605 copy_alpha_image(dest, xsize, ysize, gtc, level);
2608 case Texture::F_luminance_alphamask:
2609 case Texture::F_luminance_alpha:
2610 copy_la_image(dest, xsize, ysize, gtc, level);
2614 tinydisplay_cat.error()
2615 <<
"Unsupported texture format " 2620 bytecount += xsize * ysize * 4;
2621 xsize = max(xsize >> 1, 1);
2622 ysize = max(ysize >> 1, 1);
2643 bool TinyGraphicsStateGuardian::
2647 nassertr(tex != (
Texture *)NULL,
false);
2650 if (image_ptr == (
const unsigned char *)NULL) {
2659 _data_transferred_pcollector.add_level(image_size);
2663 if (tinydisplay_cat.is_debug()) {
2664 tinydisplay_cat.debug()
2665 <<
"loading simple image for " << tex->get_name() <<
"\n";
2668 if (!setup_gltex(gltex, width, height, 1)) {
2673 gltex->border_color.v[0] = border_color[0];
2674 gltex->border_color.v[1] = border_color[1];
2675 gltex->border_color.v[2] = border_color[2];
2676 gltex->border_color.v[3] = border_color[3];
2679 memcpy(dest->pixmap, image_ptr, image_size);
2694 bool TinyGraphicsStateGuardian::
2695 setup_gltex(
GLTexture *gltex,
int x_size,
int y_size,
int num_levels) {
2696 int s_bits = get_tex_shift(x_size);
2697 int t_bits = get_tex_shift(y_size);
2699 if (s_bits < 0 || t_bits < 0) {
2700 tinydisplay_cat.error()
2701 <<
"Texture size " << x_size <<
'x' << y_size
2702 <<
" unsupported: dimensions must be power of two" 2703 <<
" and smaller than " << _max_texture_dimension <<
'\n';
2707 num_levels = min(num_levels, MAX_MIPMAP_LEVELS);
2709 gltex->xsize = x_size;
2710 gltex->ysize = y_size;
2712 gltex->s_max = 1 << (s_bits + ZB_POINT_ST_FRAC_BITS);
2713 gltex->t_max = 1 << (t_bits + ZB_POINT_ST_FRAC_BITS);
2715 gltex->num_levels = num_levels;
2721 int total_bytecount = 0;
2727 for (
int level = 0; level < num_levels; ++level) {
2728 int bytecount = x * y * 4;
2729 total_bytecount += bytecount;
2730 x = max((x >> 1), 1);
2731 y = max((y >> 1), 1);
2735 if (gltex->total_bytecount != total_bytecount) {
2736 if (gltex->allocated_buffer != NULL) {
2737 PANDA_FREE_ARRAY(gltex->allocated_buffer);
2738 TinyTextureContext::get_class_type().dec_memory_usage(TypeHandle::MC_array, gltex->total_bytecount);
2740 gltex->allocated_buffer = PANDA_MALLOC_ARRAY(total_bytecount);
2741 gltex->total_bytecount = total_bytecount;
2742 TinyTextureContext::get_class_type().inc_memory_usage(TypeHandle::MC_array, total_bytecount);
2745 char *next_buffer = (
char *)gltex->allocated_buffer;
2746 char *end_of_buffer = next_buffer + total_bytecount;
2750 while (level < num_levels) {
2751 dest = &gltex->levels[level];
2752 int bytecount = x_size * y_size * 4;
2753 dest->pixmap = (PIXEL *)next_buffer;
2754 next_buffer += bytecount;
2755 nassertr(next_buffer <= end_of_buffer,
false);
2757 dest->s_mask = ((1 << (s_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
2758 dest->t_mask = ((1 << (t_bits + ZB_POINT_ST_FRAC_BITS)) - (1 << ZB_POINT_ST_FRAC_BITS)) << level;
2759 dest->s_shift = (ZB_POINT_ST_FRAC_BITS + level);
2760 dest->t_shift = (ZB_POINT_ST_FRAC_BITS - s_bits + level);
2762 x_size = max((x_size >> 1), 1);
2763 y_size = max((y_size >> 1), 1);
2764 s_bits = max(s_bits - 1, 0);
2765 t_bits = max(t_bits - 1, 0);
2773 while (level < MAX_MIPMAP_LEVELS) {
2774 gltex->levels[level] = *dest;
2788 int TinyGraphicsStateGuardian::
2789 get_tex_shift(
int orig_size) {
2790 if ((orig_size & (orig_size - 1)) != 0) {
2794 if (orig_size > _max_texture_dimension) {
2798 return count_bits_in_word((
unsigned int)orig_size - 1);
2807 void TinyGraphicsStateGuardian::
2815 nassertv(!src_image.is_null());
2816 const unsigned char *src = src_image.p();
2818 src += view_size * gtc->
get_view();
2822 #ifdef WORDS_BIGENDIAN 2824 static const int co = 0;
2830 unsigned int *dpix = (
unsigned int *)dest->pixmap;
2831 nassertv(dpix != NULL);
2832 const unsigned char *spix = src;
2833 int pixel_count = xsize * ysize;
2834 while (pixel_count-- > 0) {
2835 *dpix = RGBA8_TO_PIXEL(spix[co], spix[co], spix[co], 0xff);
2847 void TinyGraphicsStateGuardian::
2853 nassertv(!src_image.is_null());
2854 const unsigned char *src = src_image.p();
2856 src += view_size * gtc->
get_view();
2860 #ifdef WORDS_BIGENDIAN 2862 static const int co = 0;
2868 unsigned int *dpix = (
unsigned int *)dest->pixmap;
2869 nassertv(dpix != NULL);
2870 const unsigned char *spix = src;
2871 int pixel_count = xsize * ysize;
2872 while (pixel_count-- > 0) {
2873 *dpix = RGBA8_TO_PIXEL(0xff, 0xff, 0xff, spix[co]);
2886 void TinyGraphicsStateGuardian::
2892 nassertv(!src_image.is_null());
2893 const unsigned char *src = src_image.p();
2895 src += view_size * gtc->
get_view();
2899 #ifdef WORDS_BIGENDIAN 2901 static const int co = 0;
2907 unsigned int *dpix = (
unsigned int *)dest->pixmap;
2908 nassertv(dpix != NULL);
2909 const unsigned char *spix = src;
2910 int pixel_count = xsize * ysize;
2914 while (pixel_count-- > 0) {
2915 *dpix = RGBA8_TO_PIXEL(spix[co], 0, 0, 0xff);
2922 while (pixel_count-- > 0) {
2923 *dpix = RGBA8_TO_PIXEL(0, spix[co], 0, 0xff);
2930 while (pixel_count-- > 0) {
2931 *dpix = RGBA8_TO_PIXEL(0, 0, spix[co], 0xff);
2938 while (pixel_count-- > 0) {
2939 *dpix = RGBA8_TO_PIXEL(0, 0, 0, spix[co]);
2954 void TinyGraphicsStateGuardian::
2960 nassertv(!src_image.is_null());
2961 const unsigned char *src = src_image.p();
2963 src += view_size * gtc->
get_view();
2967 #ifdef WORDS_BIGENDIAN 2969 static const int co = 0;
2975 unsigned int *dpix = (
unsigned int *)dest->pixmap;
2976 nassertv(dpix != NULL);
2977 const unsigned char *spix = src;
2978 int pixel_count = xsize * ysize;
2980 while (pixel_count-- > 0) {
2981 *dpix = RGBA8_TO_PIXEL(spix[co], spix[co], spix[co], spix[cw + co]);
2993 void TinyGraphicsStateGuardian::
2999 nassertv(!src_image.is_null());
3000 const unsigned char *src = src_image.p();
3002 src += view_size * gtc->
get_view();
3006 #ifdef WORDS_BIGENDIAN 3008 static const int co = 0;
3014 unsigned int *dpix = (
unsigned int *)dest->pixmap;
3015 nassertv(dpix != NULL);
3016 const unsigned char *spix = src;
3017 int pixel_count = xsize * ysize;
3019 while (pixel_count-- > 0) {
3020 *dpix = RGBA8_TO_PIXEL(spix[cw + cw + co], spix[cw + co], spix[co], 0xff);
3032 void TinyGraphicsStateGuardian::
3038 nassertv(!src_image.is_null());
3039 const unsigned char *src = src_image.p();
3041 src += view_size * gtc->
get_view();
3045 #ifdef WORDS_BIGENDIAN 3047 static const int co = 0;
3053 unsigned int *dpix = (
unsigned int *)dest->pixmap;
3054 nassertv(dpix != NULL);
3055 const unsigned char *spix = src;
3056 int pixel_count = xsize * ysize;
3058 while (pixel_count-- > 0) {
3059 *dpix = RGBA8_TO_PIXEL(spix[cw + cw + co], spix[cw + co], spix[co], spix[cw + cw + cw + co]);
3071 void TinyGraphicsStateGuardian::
3074 gl_material->specular.v[0] = specular[0];
3075 gl_material->specular.v[1] = specular[1];
3076 gl_material->specular.v[2] = specular[2];
3077 gl_material->specular.v[3] = specular[3];
3080 gl_material->emission.v[0] = emission[0];
3081 gl_material->emission.v[1] = emission[1];
3082 gl_material->emission.v[2] = emission[2];
3083 gl_material->emission.v[3] = emission[3];
3086 gl_material->shininess_i = (int)((material->
get_shininess() / 128.0f) * SPECULAR_BUFFER_RESOLUTION);
3088 _color_material_flags = CMF_ambient | CMF_diffuse;
3092 gl_material->ambient.v[0] = ambient[0];
3093 gl_material->ambient.v[1] = ambient[1];
3094 gl_material->ambient.v[2] = ambient[2];
3095 gl_material->ambient.v[3] = ambient[3];
3097 _color_material_flags &= ~CMF_ambient;
3102 gl_material->diffuse.v[0] = diffuse[0];
3103 gl_material->diffuse.v[1] = diffuse[1];
3104 gl_material->diffuse.v[2] = diffuse[2];
3105 gl_material->diffuse.v[3] = diffuse[3];
3107 _color_material_flags &= ~CMF_diffuse;
3117 void TinyGraphicsStateGuardian::
3118 do_auto_rescale_normal() {
3119 if (_internal_transform->has_uniform_scale()) {
3121 _c->normalize_enabled =
false;
3122 _c->normal_scale = _internal_transform->get_uniform_scale();
3126 _c->normalize_enabled =
true;
3127 _c->normal_scale = 1.0f;
3138 void TinyGraphicsStateGuardian::
3139 load_matrix(
M4 *matrix,
const TransformState *transform) {
3140 const LMatrix4 &pm = transform->get_mat();
3141 for (
int i = 0; i < 4; ++i) {
3142 matrix->m[0][i] = pm.
get_cell(i, 0);
3143 matrix->m[1][i] = pm.
get_cell(i, 1);
3144 matrix->m[2][i] = pm.
get_cell(i, 2);
3145 matrix->m[3][i] = pm.
get_cell(i, 3);
3156 int TinyGraphicsStateGuardian::
3157 get_color_blend_op(ColorBlendAttrib::Operand operand) {
3159 case ColorBlendAttrib::O_zero:
3161 case ColorBlendAttrib::O_one:
3163 case ColorBlendAttrib::O_incoming_color:
3165 case ColorBlendAttrib::O_one_minus_incoming_color:
3167 case ColorBlendAttrib::O_fbuffer_color:
3169 case ColorBlendAttrib::O_one_minus_fbuffer_color:
3171 case ColorBlendAttrib::O_incoming_alpha:
3173 case ColorBlendAttrib::O_one_minus_incoming_alpha:
3175 case ColorBlendAttrib::O_fbuffer_alpha:
3177 case ColorBlendAttrib::O_one_minus_fbuffer_alpha:
3179 case ColorBlendAttrib::O_constant_color:
3181 case ColorBlendAttrib::O_one_minus_constant_color:
3183 case ColorBlendAttrib::O_constant_alpha:
3185 case ColorBlendAttrib::O_one_minus_constant_alpha:
3188 case ColorBlendAttrib::O_incoming_color_saturate:
3191 case ColorBlendAttrib::O_color_scale:
3193 case ColorBlendAttrib::O_one_minus_color_scale:
3195 case ColorBlendAttrib::O_alpha_scale:
3197 case ColorBlendAttrib::O_one_minus_alpha_scale:
3209 ZB_lookupTextureFunc TinyGraphicsStateGuardian::
3210 get_tex_filter_func(SamplerState::FilterType filter) {
3212 case SamplerState::FT_nearest:
3213 return &lookup_texture_nearest;
3215 case SamplerState::FT_linear:
3216 return &lookup_texture_bilinear;
3218 case SamplerState::FT_nearest_mipmap_nearest:
3219 return &lookup_texture_mipmap_nearest;
3221 case SamplerState::FT_nearest_mipmap_linear:
3222 return &lookup_texture_mipmap_linear;
3224 case SamplerState::FT_linear_mipmap_nearest:
3225 return &lookup_texture_mipmap_bilinear;
3227 case SamplerState::FT_linear_mipmap_linear:
3228 return &lookup_texture_mipmap_trilinear;
3231 return &lookup_texture_nearest;
3241 ZB_texWrapFunc TinyGraphicsStateGuardian::
3242 get_tex_wrap_func(SamplerState::WrapMode wrap_mode) {
3243 switch (wrap_mode) {
3244 case SamplerState::WM_clamp:
3245 case SamplerState::WM_border_color:
3246 return &texcoord_clamp;
3248 case SamplerState::WM_repeat:
3249 case SamplerState::WM_invalid:
3250 return &texcoord_repeat;
3252 case SamplerState::WM_mirror:
3253 return &texcoord_mirror;
3255 case SamplerState::WM_mirror_once:
3256 return &texcoord_mirror_once;
3259 return &texcoord_repeat;
3268 void TinyGraphicsStateGuardian::
3269 texgen_null(
V2 &result, TinyGraphicsStateGuardian::TexCoordData &) {
3280 void TinyGraphicsStateGuardian::
3281 texgen_simple(
V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
3283 const LVecBase2 &d = tcdata._r1.get_data2();
3294 void TinyGraphicsStateGuardian::
3295 texgen_texmat(
V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
3297 LVecBase4 d = tcdata._r1.get_data4() * tcdata._mat;
3298 result.v[0] = d[0] / d[3];
3299 result.v[1] = d[1] / d[3];
3308 void TinyGraphicsStateGuardian::
3309 texgen_sphere_map(
V2 &result, TinyGraphicsStateGuardian::TexCoordData &tcdata) {
3311 LVector3 n = tcdata._mat.xform_vec(tcdata._r1.get_data3());
3312 LVector3 u = tcdata._mat.xform_point(tcdata._r2.get_data3());
3319 LVector3 r = u - n * dot(n, u) * 2.0f;
3322 PN_stdfloat m = 2.0f * csqrt(r[0] * r[0] + r[1] * r[1] + (r[2] + 1.0f) * (r[2] + 1.0f));
3325 result.v[0] = r[0] / m + 0.5f;
3326 result.v[1] = r[1] / m + 0.5f;
virtual bool is_linear() const
Returns true if the lens represents a linear projection (e.g.
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.
int get_num_ram_mipmap_images() const
Returns the maximum number of mipmap level images available in system memory.
Format get_format() const
Returns the format of the texture, which represents both the semantic meaning of the texels and...
Texture * get_texture() const
Returns the pointer to the associated Texture object.
int get_offset() const
Returns the depth offset represented by this attrib.
bool was_image_modified() const
Returns true if the texture image has been modified since the last time mark_loaded() was called...
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.
The abstract interface to all kinds of lights.
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.
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.
virtual bool update_texture(TextureContext *tc, bool force)
Ensures that the current Texture data is refreshed onto the GSG.
int get_z_size() const
Returns the depth of the texture image in texels.
Mode get_mode() const
Returns the colorBlend mode.
Mode get_mode() const
Returns the render mode.
LColor get_border_color() const
Returns the solid color of the texture's border.
void setup_2d_texture()
Sets the texture as an empty 2-d texture with no dimensions.
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.
Material * get_material() const
If the MaterialAttrib is not an 'off' MaterialAttrib, returns the material that is associated...
virtual void do_issue_light()
This implementation of do_issue_light() assumes we have a limited number of hardware lights available...
Mode get_mode() const
Returns the shade mode.
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.
TextureType get_texture_type() const
Returns the overall interpretation of the texture.
size_t get_ram_image_size() const
Returns the total number of bytes used by the in-memory image, across all pages and views...
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" ...
int get_view() const
Returns the specific view of a multiview texture this context represents.
bool might_have_ram_image() const
Returns true if the texture's image contents are currently available in main RAM, or there is reason ...
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...
bool is_empty() const
Returns true if the NodePath contains no nodes.
Indicates which, if any, material should be applied to geometry.
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 depth buffer.
virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected triangles.
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
LPoint3 get_nodal_point() const
Returns the center point of the lens: the point from which the lens is viewing.
This is a convenience class to specialize ConfigVariable as a boolean type.
virtual void end_draw_primitives()
Called after a sequence of draw_primitive() functions are called, this should do whatever cleanup is ...
PN_stdfloat get_shininess() const
Returns the shininess exponent of the material.
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.
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...
unsigned int get_channels() const
Returns the mask of color channels that are enabled by this attrib.
Mode get_mode() const
Returns the transparency mode.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
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...
PandaCompareFunc get_mode() const
Returns the alpha write mode.
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...
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...
const LVecBase4 & get_data4()
Returns the data associated with the read row, expressed as a 4-component value, and advances the rea...
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
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 ...
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
Return the mode of this stage.
virtual void close_gsg()
This is called by the associated GraphicsWindow when close_window() is called.
int get_component_width() const
Returns the number of bytes stored for each color component of a texel.
PN_stdfloat get_hfov() const
Returns the horizontal component of fov only.
FilterType get_magfilter() const
Returns the filter mode of the texture for magnification.
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...
bool has_ram_image() const
Returns true if the Texture has its image contents available in main RAM, false if it exists only in ...
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.
ComponentType get_component_type() const
Returns the numeric interpretation of each component of the texture.
PN_stdfloat get_exponent() const FINAL
Returns the exponent that controls the amount of light falloff from the center of the spotlight...
int get_simple_y_size() const
Returns the height of the "simple" image in texels.
Mode get_mode() const
Returns the depth write mode.
void texture_uploaded(Texture *tex)
This method is called by the GraphicsStateGuardian after a texture has been successfully uploaded to ...
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...
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...
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
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...
Indicates which faces should be culled based on their vertex ordering.
Operand get_operand_a() const
Returns the multiplier for the first component.
This specialization on GeomMunger finesses vertices for TinyPanda rendering.
CPTA_uchar get_ram_mipmap_image(int n) const
Returns the system-RAM image data associated with the nth mipmap level, if present.
FilterType get_effective_minfilter() const
Returns the filter mode of the texture for minification, with special treatment for FT_default...
const LColor & get_diffuse() const
Returns the diffuse color setting, if it has been set.
bool uses_mipmaps() const
Returns true if the minfilter settings on this sampler indicate the use of mipmapping, false otherwise.
const LColor & get_ambient() const
Returns the ambient color setting, if it has been set.
A lightweight class that represents a single element that may be timed and/or counted via stats...
CPTA_uchar get_simple_ram_image() const
Returns the image data associated with the "simple" texture image.
FilterType get_minfilter() const
Returns the filter mode of the texture for minification.
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...
bool uses_mipmaps() const
Returns true if the minfilter settings on this texture indicate the use of mipmapping, false otherwise.
virtual void clear(DrawableRegion *clearable)
Clears the framebuffer within the current DisplayRegion, according to the flags indicated by the give...
const LVecBase4 & get_frame() const
Returns the left, right, bottom, top coordinates of the scissor frame.
virtual void release_texture(TextureContext *tc)
Frees the GL resources previously allocated for the texture.
This is a 4-by-4 transform matrix.
const LPoint3 & get_point() const
Returns the point in space at which the light is located.
bool get_clear_color_active() const
Returns the current setting of the flag that indicates whether the color buffer should be cleared eve...
virtual PreparedGraphicsObjects * get_prepared_objects()
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
bool has_column() const
Returns true if a valid data type has been successfully set, or false if the data type does not exist...
An object to create GraphicsOutputs that share a particular 3-D API.
bool get_clear_depth_active() const
Returns the current setting of the flag that indicates whether the depth buffer should be cleared eve...
bool has_simple_ram_image() const
Returns true if the Texture has a "simple" image available in main RAM.
const LColor & get_specular_color() const FINAL
Returns the color of specular highlights generated by the light.
const LColor & get_clear_color() const
Returns the current clear color value.
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.
LColor get_color() const
Returns the constant color associated with the attrib.
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.
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...
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...
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.
QualityLevel get_quality_level() const
Returns the current quality_level hint.
bool get_clear_stencil_active() const
Returns the current setting of the flag that indicates whether the color buffer should be cleared eve...
InternalName * get_texcoord_name() const
See set_texcoord_name.
int get_tex_view_offset() const
Returns the current setting of the tex_view_offset.
const LColor & get_specular_color() const FINAL
Returns the color of specular highlights generated by the light.
Enables or disables writing of pixel to framebuffer based on its alpha value relative to a reference ...
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.
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
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.
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
PN_stdfloat get_reference_alpha() const
Returns the alpha reference value.
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.
const LMatrix4 & get_projection_mat(StereoChannel channel=SC_mono) const
Returns the complete transformation matrix from a 3-d point in space to a point on the film...
const LVector3 & get_direction() const
Returns the direction in which the light is aimed.
This specifies how colors are blended into the frame buffer, for special effects. ...
PandaNode * node() const
Returns the referenced node of the path.
void generate_ram_mipmap_images()
Automatically fills in the n mipmap levels of the Texture, based on the texture's source image...
PandaCompareFunc get_mode() const
Returns the depth write mode.
float get_cell(int row, int col) const
Returns a particular element of the matrix.
A thread; that is, a lightweight process.
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...
This is a special kind of attribute that instructs the graphics driver to apply an offset or bias to ...
int get_y_size() const
Returns the height of the texture image in texels.
Operand get_operand_b() const
Returns the multiplier for the second component.
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.
void set_active(bool flag)
Changes the active flag associated with this object.
bool is_off() const
Returns true if the MaterialAttrib is an 'off' MaterialAttrib, indicating that it should disable the ...
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 is_null() const
Returns true if the PointerTo is a NULL pointer, false otherwise.
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...
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
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_num_components() const
Returns the number of color components for each texel of the texture image.
Mode get_effective_mode() const
Returns the effective culling mode.
This class is the main interface to controlling the render process.
This is a two-component point in space.
const LColor & get_emission() const
Returns the emission color setting, if it has been set.
virtual void reset()
Resets all internal state as if the gsg were newly created.
Mode get_mode() const
Returns the render mode.
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.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
bool has_diffuse() const
Returns true if the diffuse color has been explicitly set for this material, false otherwise...
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.
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...
virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle strips.
int get_simple_x_size() const
Returns the width of the "simple" image in texels.
WrapMode get_wrap_v() const
Returns the wrap mode of the texture in the V direction.
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer, etc.) of a drawing region.
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.
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...
const LVector3 & get_view_vector() const
Returns the axis along which the lens is facing.
WrapMode get_wrap_u() const
Returns the wrap mode of the texture in the U direction.
const LColor & get_specular() const
Returns the specular color setting, if it has been set.
A light originating from a single point in space, and shining in all directions.
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.
Similar to PointerToArray, except that its contents may not be modified.
int get_x_size() const
Returns the width of the texture image in texels.
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.
FilterType get_effective_magfilter() const
Returns the filter mode of the texture for magnification, with special treatment for FT_default...
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Prepare a display region for rendering (set up scissor region and viewport)
virtual bool draw_lines(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected line segments.