66 PStatCollector GraphicsStateGuardian::_vertex_buffer_switch_pcollector(
"Buffer switch:Vertex");
67 PStatCollector GraphicsStateGuardian::_index_buffer_switch_pcollector(
"Buffer switch:Index");
68 PStatCollector GraphicsStateGuardian::_shader_buffer_switch_pcollector(
"Buffer switch:Shader");
69 PStatCollector GraphicsStateGuardian::_load_vertex_buffer_pcollector(
"Draw:Transfer data:Vertex buffer");
70 PStatCollector GraphicsStateGuardian::_load_index_buffer_pcollector(
"Draw:Transfer data:Index buffer");
71 PStatCollector GraphicsStateGuardian::_load_shader_buffer_pcollector(
"Draw:Transfer data:Shader buffer");
72 PStatCollector GraphicsStateGuardian::_create_vertex_buffer_pcollector(
"Draw:Transfer data:Create Vertex buffer");
73 PStatCollector GraphicsStateGuardian::_create_index_buffer_pcollector(
"Draw:Transfer data:Create Index buffer");
74 PStatCollector GraphicsStateGuardian::_create_shader_buffer_pcollector(
"Draw:Transfer data:Create Shader buffer");
75 PStatCollector GraphicsStateGuardian::_load_texture_pcollector(
"Draw:Transfer data:Texture");
76 PStatCollector GraphicsStateGuardian::_data_transferred_pcollector(
"Data transferred");
77 PStatCollector GraphicsStateGuardian::_texmgrmem_total_pcollector(
"Texture manager");
78 PStatCollector GraphicsStateGuardian::_texmgrmem_resident_pcollector(
"Texture manager:Resident");
79 PStatCollector GraphicsStateGuardian::_primitive_batches_pcollector(
"Primitive batches");
80 PStatCollector GraphicsStateGuardian::_primitive_batches_tristrip_pcollector(
"Primitive batches:Triangle strips");
81 PStatCollector GraphicsStateGuardian::_primitive_batches_trifan_pcollector(
"Primitive batches:Triangle fans");
82 PStatCollector GraphicsStateGuardian::_primitive_batches_tri_pcollector(
"Primitive batches:Triangles");
83 PStatCollector GraphicsStateGuardian::_primitive_batches_patch_pcollector(
"Primitive batches:Patches");
84 PStatCollector GraphicsStateGuardian::_primitive_batches_other_pcollector(
"Primitive batches:Other");
85 PStatCollector GraphicsStateGuardian::_vertices_tristrip_pcollector(
"Vertices:Triangle strips");
86 PStatCollector GraphicsStateGuardian::_vertices_trifan_pcollector(
"Vertices:Triangle fans");
87 PStatCollector GraphicsStateGuardian::_vertices_tri_pcollector(
"Vertices:Triangles");
88 PStatCollector GraphicsStateGuardian::_vertices_patch_pcollector(
"Vertices:Patches");
89 PStatCollector GraphicsStateGuardian::_vertices_other_pcollector(
"Vertices:Other");
90 PStatCollector GraphicsStateGuardian::_state_pcollector(
"State changes");
91 PStatCollector GraphicsStateGuardian::_transform_state_pcollector(
"State changes:Transforms");
92 PStatCollector GraphicsStateGuardian::_texture_state_pcollector(
"State changes:Textures");
93 PStatCollector GraphicsStateGuardian::_draw_primitive_pcollector(
"Draw:Primitive:Draw");
94 PStatCollector GraphicsStateGuardian::_draw_set_state_pcollector(
"Draw:Set State");
95 PStatCollector GraphicsStateGuardian::_flush_pcollector(
"Draw:Flush");
96 PStatCollector GraphicsStateGuardian::_compute_dispatch_pcollector(
"Draw:Compute dispatch");
98 PStatCollector GraphicsStateGuardian::_wait_occlusion_pcollector(
"Wait:Occlusion");
99 PStatCollector GraphicsStateGuardian::_wait_timer_pcollector(
"Wait:Timer Queries");
100 PStatCollector GraphicsStateGuardian::_timer_queries_pcollector(
"Timer queries");
101 PStatCollector GraphicsStateGuardian::_command_latency_pcollector(
"Command latency");
103 PStatCollector GraphicsStateGuardian::_prepare_pcollector(
"Draw:Prepare");
104 PStatCollector GraphicsStateGuardian::_prepare_texture_pcollector(
"Draw:Prepare:Texture");
105 PStatCollector GraphicsStateGuardian::_prepare_sampler_pcollector(
"Draw:Prepare:Sampler");
106 PStatCollector GraphicsStateGuardian::_prepare_geom_pcollector(
"Draw:Prepare:Geom");
107 PStatCollector GraphicsStateGuardian::_prepare_shader_pcollector(
"Draw:Prepare:Shader");
108 PStatCollector GraphicsStateGuardian::_prepare_vertex_buffer_pcollector(
"Draw:Prepare:Vertex buffer");
109 PStatCollector GraphicsStateGuardian::_prepare_index_buffer_pcollector(
"Draw:Prepare:Index buffer");
110 PStatCollector GraphicsStateGuardian::_prepare_shader_buffer_pcollector(
"Draw:Prepare:Shader buffer");
112 PStatCollector GraphicsStateGuardian::_draw_set_state_transform_pcollector(
"Draw:Set State:Transform");
113 PStatCollector GraphicsStateGuardian::_draw_set_state_alpha_test_pcollector(
"Draw:Set State:Alpha test");
114 PStatCollector GraphicsStateGuardian::_draw_set_state_antialias_pcollector(
"Draw:Set State:Antialias");
115 PStatCollector GraphicsStateGuardian::_draw_set_state_clip_plane_pcollector(
"Draw:Set State:Clip plane");
116 PStatCollector GraphicsStateGuardian::_draw_set_state_color_pcollector(
"Draw:Set State:Color");
117 PStatCollector GraphicsStateGuardian::_draw_set_state_cull_face_pcollector(
"Draw:Set State:Cull face");
118 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_offset_pcollector(
"Draw:Set State:Depth offset");
119 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_test_pcollector(
"Draw:Set State:Depth test");
120 PStatCollector GraphicsStateGuardian::_draw_set_state_depth_write_pcollector(
"Draw:Set State:Depth write");
121 PStatCollector GraphicsStateGuardian::_draw_set_state_render_mode_pcollector(
"Draw:Set State:Render mode");
122 PStatCollector GraphicsStateGuardian::_draw_set_state_rescale_normal_pcollector(
"Draw:Set State:Rescale normal");
123 PStatCollector GraphicsStateGuardian::_draw_set_state_shade_model_pcollector(
"Draw:Set State:Shade model");
124 PStatCollector GraphicsStateGuardian::_draw_set_state_blending_pcollector(
"Draw:Set State:Blending");
125 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_pcollector(
"Draw:Set State:Shader");
126 PStatCollector GraphicsStateGuardian::_draw_set_state_shader_parameters_pcollector(
"Draw:Set State:Shader Parameters");
127 PStatCollector GraphicsStateGuardian::_draw_set_state_texture_pcollector(
"Draw:Set State:Texture");
128 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_matrix_pcollector(
"Draw:Set State:Tex matrix");
129 PStatCollector GraphicsStateGuardian::_draw_set_state_tex_gen_pcollector(
"Draw:Set State:Tex gen");
130 PStatCollector GraphicsStateGuardian::_draw_set_state_material_pcollector(
"Draw:Set State:Material");
131 PStatCollector GraphicsStateGuardian::_draw_set_state_light_pcollector(
"Draw:Set State:Light");
132 PStatCollector GraphicsStateGuardian::_draw_set_state_stencil_pcollector(
"Draw:Set State:Stencil");
133 PStatCollector GraphicsStateGuardian::_draw_set_state_fog_pcollector(
"Draw:Set State:Fog");
134 PStatCollector GraphicsStateGuardian::_draw_set_state_scissor_pcollector(
"Draw:Set State:Scissor");
136 PT(
TextureStage) GraphicsStateGuardian::_alpha_scale_texture_stage =
nullptr;
138 TypeHandle GraphicsStateGuardian::_type_handle;
144 GraphicsStateGuardian::
145 GraphicsStateGuardian(CoordinateSystem internal_coordinate_system,
147 _internal_coordinate_system(internal_coordinate_system),
151 _coordinate_system = CS_invalid;
152 _internal_transform = TransformState::make_identity();
154 if (_internal_coordinate_system == CS_default) {
155 _internal_coordinate_system = get_default_coordinate_system();
158 set_coordinate_system(get_default_coordinate_system());
160 _data_reader =
nullptr;
161 _current_display_region =
nullptr;
162 _current_stereo_channel = Lens::SC_mono;
163 _current_tex_view_offset = 0;
164 _current_lens =
nullptr;
165 _projection_mat = TransformState::make_identity();
166 _projection_mat_inv = TransformState::make_identity();
170 _current_properties =
nullptr;
171 _closing_gsg =
false;
174 _stereo_buffer_mask = ~0;
175 _incomplete_render = allow_incomplete_render;
176 _effective_incomplete_render =
false;
179 _is_hardware =
false;
180 _prefers_triangle_strips =
false;
181 _max_vertices_per_array = INT_MAX;
182 _max_vertices_per_primitive = INT_MAX;
186 _max_texture_stages = 1;
190 _max_texture_dimension = -1;
191 _max_3d_texture_dimension = 0;
192 _max_2d_texture_array_layers = 0;
193 _max_cube_map_dimension = 0;
194 _max_buffer_texture_size = 0;
197 _supports_texture_combine =
false;
198 _supports_texture_saved_result =
false;
199 _supports_texture_dot3 =
false;
201 _supports_3d_texture =
false;
202 _supports_2d_texture_array =
false;
203 _supports_cube_map =
false;
204 _supports_buffer_texture =
false;
205 _supports_cube_map_array =
false;
206 _supports_tex_non_pow2 =
false;
207 _supports_texture_srgb =
false;
208 _supports_compressed_texture =
false;
209 _compressed_texture_formats.clear();
210 _compressed_texture_formats.set_bit(Texture::CM_off);
214 _max_clip_planes = -1;
217 _max_vertex_transforms = 0;
218 _max_vertex_transform_indices = 0;
220 _supports_occlusion_query =
false;
221 _supports_timer_query =
false;
224 _timer_queries_active =
false;
225 _last_query_frame = 0;
226 _last_num_queried = 0;
229 _pstats_gpu_thread = -1;
234 _copy_texture_inverted =
false;
237 _supports_multisample =
false;
238 _supports_generate_mipmap =
false;
239 _supports_depth_texture =
false;
240 _supports_depth_stencil =
false;
241 _supports_shadow_filter =
false;
242 _supports_sampler_objects =
false;
243 _supports_basic_shaders =
false;
244 _supports_geometry_shaders =
false;
245 _supports_tessellation_shaders =
false;
246 _supports_compute_shaders =
false;
247 _supports_glsl =
false;
248 _supports_hlsl =
false;
250 _supports_stencil =
false;
251 _supports_stencil_wrap =
false;
252 _supports_two_sided_stencil =
false;
253 _supports_geometry_instancing =
false;
254 _supports_indirect_draw =
false;
257 _supports_luminance_texture =
true;
260 _max_color_targets = 1;
261 _supports_dual_source_blending =
false;
263 _supported_geom_rendering = 0;
268 _color_scale_via_lighting = color_scale_via_lighting;
271 _alpha_scale_via_texture = alpha_scale_via_texture;
275 _runtime_color_scale =
false;
278 _auto_detect_shader_model = SM_00;
279 _shader_model = SM_00;
282 _texture_quality_override = Texture::QL_default;
286 static size_t next_index = 0;
293 GraphicsStateGuardian::
294 ~GraphicsStateGuardian() {
305 for (
size_t si = 0; si < size; ++si) {
307 state->_mungers.
remove(_id);
308 state->_munged_states.
remove(_id);
319 nassertr(_engine !=
nullptr, GraphicsEngine::get_global_ptr());
334 return _supports_multisample;
348 return _supported_geom_rendering;
371 if (cs == CS_default) {
372 cs = get_default_coordinate_system();
374 if (_coordinate_system == cs) {
377 _coordinate_system = cs;
380 if (_internal_coordinate_system == CS_default ||
381 _internal_coordinate_system == _coordinate_system) {
382 _cs_transform = TransformState::make_identity();
383 _inv_cs_transform = TransformState::make_identity();
387 TransformState::make_mat
388 (LMatrix4::convert_mat(_coordinate_system,
389 _internal_coordinate_system));
391 TransformState::make_mat
392 (LMatrix4::convert_mat(_internal_coordinate_system,
393 _coordinate_system));
408 return _internal_coordinate_system;
417 return _prepared_objects;
451 void *callback_arg) {
453 PreparedGraphicsObjects::Textures::const_iterator ti;
454 for (ti = _prepared_objects->_prepared_textures.begin();
455 ti != _prepared_objects->_prepared_textures.end();
457 bool result = (*func)(*ti, callback_arg);
484 _flash_texture = tex;
495 _flash_texture =
nullptr;
506 return _flash_texture;
520 _scene_setup = scene_setup;
521 _current_lens = scene_setup->
get_lens();
522 if (_current_lens ==
nullptr) {
528 _projection_mat = calc_projection_mat(_current_lens);
529 if (_projection_mat ==
nullptr) {
532 _projection_mat_inv = _projection_mat->get_inverse();
716 nassertv(_current_occlusion_query ==
nullptr);
726 end_occlusion_query() {
727 nassertr(_current_occlusion_query !=
nullptr,
nullptr);
729 _current_occlusion_query =
nullptr;
738 issue_timer_query(
int pstats_index) {
748 nassert_raise(
"Compute shaders not supported by GSG");
764 int mi = state->_last_mi;
767 if (munger->is_registered()) {
773 mi = mungers.
find(_id);
776 if (munger->is_registered()) {
777 state->_last_mi = mi;
787 PT(
GeomMunger) munger = make_geom_munger(state, current_thread);
788 nassertr(munger !=
nullptr && munger->is_registered(), munger);
789 nassertr(munger->is_of_type(StateMunger::get_class_type()), munger);
791 state->_last_mi = mungers.
store(_id, munger);
814 switch (_internal_coordinate_system) {
829 <<
"Invalid coordinate system in compute_distance_to: "
830 << (int)_internal_coordinate_system <<
"\n";
864 if (altered & spec._dep[0]) {
865 const LMatrix4 *t =
fetch_specified_part(spec._part[0], spec._arg[0], spec._cache[0], spec._index);
866 if (t != &spec._cache[0]) {
870 if (altered & spec._dep[1]) {
871 const LMatrix4 *t =
fetch_specified_part(spec._part[1], spec._arg[1], spec._cache[1], spec._index);
872 if (t != &spec._cache[1]) {
878 case Shader::SMF_compose:
879 spec._value.multiply(spec._cache[0], spec._cache[1]);
881 case Shader::SMF_transform_dlight:
882 spec._value = spec._cache[0];
883 v = spec._cache[1].xform_vec(spec._cache[0].get_row3(2));
885 spec._value.set_row(2, v);
886 v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3));
888 spec._value.set_row(3, v);
890 case Shader::SMF_transform_plight:
893 spec._value = spec._cache[0];
894 LPoint3 point = spec._cache[1].xform_point(spec._cache[0].get_row3(2));
895 spec._value(2, 0) = point[0];
896 spec._value(2, 1) = point[1];
897 spec._value(2, 2) = point[2];
900 case Shader::SMF_transform_slight:
901 spec._value = spec._cache[0];
902 spec._value.set_row(2, spec._cache[1].xform_point(spec._cache[0].get_row3(2)));
903 v = spec._cache[1].xform_vec(spec._cache[0].get_row3(3));
905 spec._value.set_row(3, v);
907 case Shader::SMF_first:
908 return &spec._cache[0];
911 spec._value = LMatrix4::ident_mat();
921 LMatrix4 &t,
int index) {
923 case Shader::SMO_identity: {
924 return &LMatrix4::ident_mat();
926 case Shader::SMO_window_size:
927 case Shader::SMO_pixel_size: {
928 LVecBase2i pixel_size = _current_display_region->get_pixel_size();
929 t = LMatrix4::translate_mat(pixel_size[0], pixel_size[1], 0);
932 case Shader::SMO_frame_time: {
934 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, time, time, time, time);
937 case Shader::SMO_frame_delta: {
939 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dt, dt, dt, dt);
942 case Shader::SMO_texpad_x: {
943 Texture *tex = _target_shader->get_shader_input_texture(name);
944 nassertr(tex !=
nullptr, &LMatrix4::zeros_mat());
951 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cx, cy, cz, 0);
954 case Shader::SMO_texpix_x: {
955 Texture *tex = _target_shader->get_shader_input_texture(name);
956 nassertr(tex !=
nullptr, &LMatrix4::zeros_mat());
960 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, px, py, pz, 0);
963 case Shader::SMO_attr_material: {
965 _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
967 if (target_material->
is_off()) {
968 t.set(1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0);
977 t.set(amb[0], amb[1], amb[2], amb[3],
978 dif[0], dif[1], dif[2], dif[3],
979 emm[0], emm[1], emm[2], emm[3],
980 spc[0], spc[1], spc[2], spc[3]);
983 case Shader::SMO_attr_material2: {
985 _target_rs->get_attrib_def(MaterialAttrib::get_class_slot());
986 if (target_material->
is_off()) {
987 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1);
995 case Shader::SMO_attr_color: {
997 _target_rs->get_attrib_def(ColorAttrib::get_class_slot());
999 return &LMatrix4::ones_mat();
1001 LVecBase4 c = target_color->
get_color();
1002 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
1005 case Shader::SMO_attr_colorscale: {
1007 _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot());
1009 return &LMatrix4::ones_mat();
1011 LVecBase4 cs = target_color->
get_scale();
1012 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, cs[0], cs[1], cs[2], cs[3]);
1015 case Shader::SMO_attr_fog: {
1017 _target_rs->get_attrib_def(FogAttrib::get_class_slot());
1019 if (fog ==
nullptr) {
1020 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1);
1023 PN_stdfloat start, end;
1025 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1029 case Shader::SMO_attr_fogcolor: {
1031 _target_rs->get_attrib_def(FogAttrib::get_class_slot());
1033 if (fog ==
nullptr) {
1034 return &LMatrix4::ones_mat();
1037 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
1040 case Shader::SMO_alight_x: {
1041 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1042 nassertr(!np.
is_empty(), &LMatrix4::zeros_mat());
1044 DCAST_INTO_R(lt, np.
node(), &LMatrix4::zeros_mat());
1046 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, c[0], c[1], c[2], c[3]);
1049 case Shader::SMO_satten_x: {
1050 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1051 nassertr(!np.
is_empty(), &LMatrix4::ones_mat());
1053 DCAST_INTO_R(lt, np.
node(), &LMatrix4::ones_mat());
1056 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, a[0], a[1], a[2], x);
1059 case Shader::SMO_dlight_x: {
1061 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1062 nassertr(!np.
is_empty(), &LMatrix4::zeros_mat());
1064 DCAST_INTO_R(lt, np.
node(), &LMatrix4::zeros_mat());
1067 t = np.get_net_transform()->
get_mat() *
1068 _scene_setup->get_world_transform()->get_mat();
1071 LVecBase3 h = d + LVecBase3(0,-1,0);
1073 t.set(c[0], c[1], c[2], c[3],
1074 s[0], s[1], s[2], c[3],
1075 d[0], d[1], d[2], 0,
1076 h[0], h[1], h[2], 0);
1079 case Shader::SMO_plight_x: {
1081 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1082 nassertr(!np.
is_empty(), &LMatrix4::ones_mat());
1084 DCAST_INTO_R(lt, np.
node(), &LMatrix4::zeros_mat());
1087 t = np.get_net_transform()->
get_mat() *
1088 _scene_setup->get_world_transform()->get_mat();
1089 LVecBase3 p = (t.xform_point(lt->
get_point()));
1092 PN_stdfloat lnear = lens->
get_near();
1093 PN_stdfloat lfar = lens->
get_far();
1094 t.set(c[0], c[1], c[2], c[3],
1095 s[0], s[1], s[2], s[3],
1096 p[0], p[1], p[2], lnear,
1097 a[0], a[1], a[2], lfar);
1100 case Shader::SMO_slight_x: {
1102 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1103 nassertr(!np.
is_empty(), &LMatrix4::zeros_mat());
1105 DCAST_INTO_R(lt, np.
node(), &LMatrix4::zeros_mat());
1107 nassertr(lens !=
nullptr, &LMatrix4::zeros_mat());
1110 PN_stdfloat cutoff = ccos(deg_2_rad(lens->
get_hfov() * 0.5f));
1111 t = np.get_net_transform()->
get_mat() *
1112 _scene_setup->get_world_transform()->get_mat();
1115 t.set(c[0], c[1], c[2], c[3],
1116 s[0], s[1], s[2], s[3],
1117 p[0], p[1], p[2], 0,
1118 d[0], d[1], d[2], cutoff);
1121 case Shader::SMO_light_ambient: {
1122 LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
1124 _target_rs->get_attrib_def(LightAttrib::get_class_slot());
1129 t.set_row(3, LVecBase4(1, 1, 1, 1));
1131 t.set_row(3, target_light->get_ambient_contribution());
1135 case Shader::SMO_texmat_i: {
1138 if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1142 return &LMatrix4::ident_mat();
1145 case Shader::SMO_inv_texmat_i: {
1148 if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1149 index < ta->get_num_on_stages()) {
1150 t = tma->get_transform(ta->
get_on_stage(index))->get_inverse()->get_mat();
1153 return &LMatrix4::ident_mat();
1156 case Shader::SMO_texscale_i: {
1159 if (_target_rs->get_attrib(ta) && _target_rs->get_attrib(tma) &&
1160 index < ta->get_num_on_stages()) {
1161 LVecBase3 scale = tma->get_transform(ta->
get_on_stage(index))->get_scale();
1162 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, scale[0], scale[1], scale[2], 0);
1165 return &LMatrix4::ident_mat();
1168 case Shader::SMO_texcolor_i: {
1170 if (_target_rs->get_attrib(ta) && index < ta->get_num_on_stages()) {
1175 return &LMatrix4::zeros_mat();
1178 case Shader::SMO_tex_is_alpha_i: {
1182 if (_target_rs->get_attrib(ta) &&
1183 index < ta->get_num_on_stages()) {
1185 PN_stdfloat v = (ta->
get_on_texture(ts)->get_format() == Texture::F_alpha);
1186 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, v, v, v, 0);
1189 return &LMatrix4::zeros_mat();
1192 case Shader::SMO_plane_x: {
1193 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1194 nassertr(!np.
is_empty(), &LMatrix4::zeros_mat());
1196 DCAST_INTO_R(plane_node, np.
node(), &LMatrix4::zeros_mat());
1198 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, p[0], p[1], p[2], p[3]);
1201 case Shader::SMO_clipplane_x: {
1203 _target_rs->get_attrib_def(cpa);
1204 int planenr = atoi(name->
get_name().c_str());
1206 return &LMatrix4::zeros_mat();
1209 nassertr(!np.
is_empty(), &LMatrix4::zeros_mat());
1211 DCAST_INTO_R(plane_node, np.
node(), &LMatrix4::zeros_mat());
1216 if (!transform->is_identity()) {
1217 plane.xform(transform->get_mat());
1219 t.set_row(3, plane);
1222 case Shader::SMO_apiview_clipplane_i: {
1224 _target_rs->get_attrib_def(cpa);
1226 return &LMatrix4::zeros_mat();
1230 nassertr(!plane.
is_empty(), &LMatrix4::zeros_mat());
1232 DCAST_INTO_R(plane_node, plane.
node(), &LMatrix4::zeros_mat());
1235 _scene_setup->get_cs_world_transform()->compose(
1236 plane.
get_transform(_scene_setup->get_scene_root().get_parent()));
1238 LPlane xformed_plane = plane_node->
get_plane() * transform->get_mat();
1239 t.set_row(3, xformed_plane);
1242 case Shader::SMO_mat_constant_x: {
1243 return &_target_shader->get_shader_input_matrix(name, t);
1245 case Shader::SMO_vec_constant_x: {
1246 const LVecBase4 &input = _target_shader->get_shader_input_vector(name);
1247 const PN_stdfloat *data = input.get_data();
1248 t.set(data[0], data[1], data[2], data[3],
1249 data[0], data[1], data[2], data[3],
1250 data[0], data[1], data[2], data[3],
1251 data[0], data[1], data[2], data[3]);
1254 case Shader::SMO_world_to_view: {
1255 return &(_scene_setup->get_world_transform()->get_mat());
1257 case Shader::SMO_view_to_world: {
1258 return &(_scene_setup->get_camera_transform()->get_mat());
1260 case Shader::SMO_model_to_view: {
1261 t = _inv_cs_transform->compose(_internal_transform)->get_mat();
1264 case Shader::SMO_model_to_apiview: {
1265 return &(_internal_transform->get_mat());
1267 case Shader::SMO_view_to_model: {
1268 t = _internal_transform->invert_compose(_cs_transform)->get_mat();
1271 case Shader::SMO_apiview_to_model: {
1272 t = _internal_transform->get_inverse()->get_mat();
1275 case Shader::SMO_apiview_to_view: {
1276 return &(_inv_cs_transform->get_mat());
1278 case Shader::SMO_view_to_apiview: {
1279 return &(_cs_transform->get_mat());
1281 case Shader::SMO_clip_to_view: {
1282 if (_current_lens->get_coordinate_system() == _coordinate_system) {
1283 return &(_current_lens->get_projection_mat_inv(_current_stereo_channel));
1285 t = _current_lens->get_projection_mat_inv(_current_stereo_channel) *
1286 LMatrix4::convert_mat(_current_lens->get_coordinate_system(), _coordinate_system);
1290 case Shader::SMO_view_to_clip: {
1291 if (_current_lens->get_coordinate_system() == _coordinate_system) {
1292 return &(_current_lens->get_projection_mat(_current_stereo_channel));
1294 t = LMatrix4::convert_mat(_coordinate_system, _current_lens->get_coordinate_system()) *
1295 _current_lens->get_projection_mat(_current_stereo_channel);
1299 case Shader::SMO_apiclip_to_view: {
1300 t = _projection_mat_inv->get_mat() * _inv_cs_transform->get_mat();
1303 case Shader::SMO_view_to_apiclip: {
1304 t = _cs_transform->get_mat() * _projection_mat->get_mat();
1307 case Shader::SMO_apiclip_to_apiview: {
1308 return &(_projection_mat_inv->get_mat());
1310 case Shader::SMO_apiview_to_apiclip: {
1311 return &(_projection_mat->get_mat());
1313 case Shader::SMO_view_x_to_view: {
1314 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1315 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1316 t = np.get_net_transform()->
get_mat() *
1317 _scene_setup->get_world_transform()->get_mat();
1320 case Shader::SMO_view_to_view_x: {
1321 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1322 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1323 t = _scene_setup->get_camera_transform()->get_mat() *
1324 np.get_net_transform()->get_inverse()->
get_mat();
1327 case Shader::SMO_apiview_x_to_view: {
1328 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1329 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1330 t = LMatrix4::convert_mat(_internal_coordinate_system, _coordinate_system) *
1331 np.get_net_transform()->
get_mat() *
1332 _scene_setup->get_world_transform()->get_mat();
1335 case Shader::SMO_view_to_apiview_x: {
1336 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1337 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1338 t = (_scene_setup->get_camera_transform()->get_mat() *
1339 np.get_net_transform()->get_inverse()->
get_mat() *
1340 LMatrix4::convert_mat(_coordinate_system, _internal_coordinate_system));
1343 case Shader::SMO_clip_x_to_view: {
1344 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1345 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1347 DCAST_INTO_R(node, np.
node(), &LMatrix4::ident_mat());
1351 np.get_net_transform()->
get_mat() *
1352 _scene_setup->get_world_transform()->get_mat();
1355 case Shader::SMO_view_to_clip_x: {
1356 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1357 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1359 DCAST_INTO_R(node, np.
node(), &LMatrix4::ident_mat());
1361 t = _scene_setup->get_camera_transform()->get_mat() *
1362 np.get_net_transform()->get_inverse()->
get_mat() *
1367 case Shader::SMO_apiclip_x_to_view: {
1368 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1369 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1371 DCAST_INTO_R(node, np.
node(), &LMatrix4::ident_mat());
1373 t = calc_projection_mat(lens)->get_inverse()->get_mat() *
1375 np.get_net_transform()->
get_mat() *
1376 _scene_setup->get_world_transform()->get_mat();
1379 case Shader::SMO_view_to_apiclip_x: {
1380 const NodePath &np = _target_shader->get_shader_input_nodepath(name);
1381 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1383 DCAST_INTO_R(node, np.
node(), &LMatrix4::ident_mat());
1385 t = _scene_setup->get_camera_transform()->get_mat() *
1386 np.get_net_transform()->get_inverse()->
get_mat() *
1388 calc_projection_mat(lens)->get_mat();
1391 case Shader::SMO_mat_constant_x_attrib: {
1392 if (_target_shader->has_shader_input(name)) {
1395 return &_target_shader->get_shader_input_matrix(name, t);
1399 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1403 case Shader::SMO_vec_constant_x_attrib: {
1404 if (_target_shader->has_shader_input(name)) {
1407 const LVecBase4 &data = _target_shader->get_shader_input_vector(name);
1408 t.set(data[0], data[1], data[2], data[3],
1409 data[0], data[1], data[2], data[3],
1410 data[0], data[1], data[2], data[3],
1411 data[0], data[1], data[2], data[3]);
1416 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1420 case Shader::SMO_light_source_i_attrib: {
1422 _target_rs->get_attrib_def(target_light);
1427 if (index >= 0 && (
size_t)index < num_lights) {
1429 nassertr(!light.
is_empty(), &LMatrix4::ident_mat());
1431 nassertr(light_obj !=
nullptr, &LMatrix4::ident_mat());
1435 }
else if (index == 0) {
1439 return &LMatrix4::ones_mat();
1443 case Shader::SMO_light_source_i_packed: {
1446 _target_rs->get_attrib_def(target_light);
1451 if (index >= 0 && (
size_t)index < num_lights) {
1453 nassertr(!np.
is_empty(), &LMatrix4::ident_mat());
1456 nassertr(light !=
nullptr, &LMatrix4::zeros_mat());
1460 LMatrix4 mat = np.get_net_transform()->
get_mat() *
1461 _scene_setup->get_world_transform()->get_mat();
1463 if (node->
is_of_type(DirectionalLight::get_class_type())) {
1464 LVecBase3 d = mat.xform_vec(((
const DirectionalLight *)node)->get_direction());
1466 t.set_row(2, LVecBase4(d, 0));
1467 t.set_row(3, LVecBase4(-d, 0));
1469 }
else if (node->
is_of_type(LightLensNode::get_class_type())) {
1473 t.set_row(3, LVecBase4(p));
1477 if (node->
is_of_type(Spotlight::get_class_type())) {
1478 PN_stdfloat cutoff = ccos(deg_2_rad(lens->
get_hfov() * 0.5f));
1480 t.set_cell(1, 3, ((
const Spotlight *)node)->get_exponent());
1481 t.set_row(2, LVecBase4(d, cutoff));
1483 }
else if (node->
is_of_type(PointLight::get_class_type())) {
1484 t.set_cell(1, 3, lens->
get_far());
1485 t.set_cell(3, 3, lens->
get_near());
1487 if (node->
is_of_type(SphereLight::get_class_type())) {
1488 t.set_cell(2, 3, ((
const SphereLight *)node)->get_radius());
1492 }
else if (index == 0) {
1495 t.set_row(0, LVecBase4(1, 1, 1, 1));
1500 nassertr(
false , &LMatrix4::ident_mat());
1501 return &LMatrix4::ident_mat();
1523 static const CPT_InternalName IN_constantAttenuation(
"constantAttenuation");
1525 static const CPT_InternalName IN_quadraticAttenuation(
"quadraticAttenuation");
1533 if (attrib == IN_color) {
1534 if (node ==
nullptr) {
1535 return &LMatrix4::ident_mat();
1538 nassertr(light !=
nullptr, &LMatrix4::ident_mat());
1543 }
else if (attrib == IN_ambient) {
1544 if (node ==
nullptr) {
1545 return &LMatrix4::ident_mat();
1548 nassertr(light !=
nullptr, &LMatrix4::ident_mat());
1554 t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
1558 }
else if (attrib == IN_diffuse) {
1559 if (node ==
nullptr) {
1560 return &LMatrix4::ident_mat();
1563 nassertr(light !=
nullptr, &LMatrix4::ones_mat());
1566 t.set_row(3, LColor(0.0f, 0.0f, 0.0f, 1.0f));
1573 }
else if (attrib == IN_specular) {
1574 if (node ==
nullptr) {
1575 return &LMatrix4::ident_mat();
1578 nassertr(light !=
nullptr, &LMatrix4::ones_mat());
1582 }
else if (attrib == IN_position) {
1584 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
1588 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1590 }
else if (node->
is_of_type(DirectionalLight::get_class_type())) {
1592 DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1595 LVector3 dir = -(light->
get_direction() * transform->get_mat());
1596 dir *= _scene_setup->get_cs_world_transform()->
get_mat();
1597 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 0);
1601 DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1603 nassertr(lens !=
nullptr, &LMatrix4::ident_mat());
1606 _scene_setup->get_cs_world_transform()->compose(
1607 np.
get_transform(_scene_setup->get_scene_root().get_parent()));
1609 const LMatrix4 &light_mat = transform->get_mat();
1611 t = LMatrix4::translate_mat(pos);
1615 }
else if (attrib == IN_halfVector) {
1617 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0);
1621 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
1623 }
else if (node->
is_of_type(DirectionalLight::get_class_type())) {
1625 DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1628 LVector3 dir = -(light->
get_direction() * transform->get_mat());
1629 dir *= _scene_setup->get_cs_world_transform()->
get_mat();
1631 dir += LVector3(0, 0, 1);
1633 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, dir[0], dir[1], dir[2], 1);
1637 DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1639 nassertr(lens !=
nullptr, &LMatrix4::ident_mat());
1642 _scene_setup->get_cs_world_transform()->compose(
1643 np.
get_transform(_scene_setup->get_scene_root().get_parent()));
1645 const LMatrix4 &light_mat = transform->get_mat();
1648 pos += LVector3(0, 0, 1);
1650 t.set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, pos[0],pos[1],pos[2], 1);
1654 }
else if (attrib == IN_spotDirection) {
1655 if (node ==
nullptr) {
1656 t.set_row(3, LVector3(0.0f, 0.0f, -1.0f));
1660 t.set_row(3, LVector3(0.0f, 0.0f, 0.0f));
1664 DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1666 nassertr(lens !=
nullptr, &LMatrix4::ident_mat());
1669 _scene_setup->get_cs_world_transform()->compose(
1670 np.
get_transform(_scene_setup->get_scene_root().get_parent()));
1672 const LMatrix4 &light_mat = transform->get_mat();
1678 }
else if (attrib == IN_spotCutoff) {
1679 if (node !=
nullptr &&
1680 node->
is_of_type(Spotlight::get_class_type())) {
1682 DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1684 nassertr(lens !=
nullptr, &LMatrix4::ident_mat());
1686 float cutoff = lens->
get_hfov() * 0.5f;
1687 t.set_row(3, LVecBase4(cutoff));
1691 t.set_row(3, LVecBase4(180));
1695 }
else if (attrib == IN_spotCosCutoff) {
1696 if (node !=
nullptr &&
1697 node->
is_of_type(Spotlight::get_class_type())) {
1699 DCAST_INTO_R(light, node, &LMatrix4::ident_mat());
1701 nassertr(lens !=
nullptr, &LMatrix4::ident_mat());
1703 float cutoff = lens->
get_hfov() * 0.5f;
1704 t.set_row(3, LVecBase4(ccos(deg_2_rad(cutoff))));
1708 t.set_row(3, LVecBase4(-1));
1712 }
else if (attrib == IN_spotExponent) {
1713 if (node ==
nullptr) {
1714 return &LMatrix4::zeros_mat();
1717 nassertr(light !=
nullptr, &LMatrix4::ident_mat());
1722 }
else if (attrib == IN_attenuation) {
1723 if (node !=
nullptr) {
1725 nassertr(light !=
nullptr, &LMatrix4::ones_mat());
1729 t.set_row(3, LVecBase4(1, 0, 0, 0));
1733 }
else if (attrib == IN_constantAttenuation) {
1734 if (node ==
nullptr) {
1735 return &LMatrix4::ones_mat();
1738 nassertr(light !=
nullptr, &LMatrix4::ones_mat());
1743 }
else if (attrib == IN_linearAttenuation) {
1744 if (node ==
nullptr) {
1745 return &LMatrix4::zeros_mat();
1748 nassertr(light !=
nullptr, &LMatrix4::ident_mat());
1753 }
else if (attrib == IN_quadraticAttenuation) {
1754 if (node ==
nullptr) {
1755 return &LMatrix4::zeros_mat();
1758 nassertr(light !=
nullptr, &LMatrix4::ident_mat());
1763 }
else if (attrib == IN_shadowViewMatrix) {
1764 static const LMatrix4 biasmat(0.5f, 0.0f, 0.0f, 0.0f,
1765 0.0f, 0.5f, 0.0f, 0.0f,
1766 0.0f, 0.0f, 0.5f, 0.0f,
1767 0.5f, 0.5f, 0.5f, 1.0f);
1769 if (node ==
nullptr) {
1774 DCAST_INTO_R(lnode, node, &LMatrix4::ident_mat());
1777 t = _inv_cs_transform->get_mat() *
1778 _scene_setup->get_camera_transform()->get_mat() *
1779 np.get_net_transform()->get_inverse()->
get_mat() *
1782 if (!node->
is_of_type(PointLight::get_class_type())) {
1789 <<
"Shader input requests invalid attribute " << *attrib
1790 <<
" from node " << np <<
"\n";
1791 return &LMatrix4::ident_mat();
1802 static PT(
Texture) default_add_tex;
1803 static PT(
Texture) default_normal_height_tex;
1805 switch (spec._part) {
1806 case Shader::STO_named_input:
1808 if (!_target_shader->has_shader_input(spec._name)) {
1811 if (parent != InternalName::get_root() &&
1812 _target_shader->has_shader_input(parent)) {
1815 const string &basename = spec._name->get_basename();
1816 NodePath np = _target_shader->get_shader_input_nodepath(parent);
1818 if (basename ==
"shadowMap") {
1819 PT(
Texture) tex = get_shadow_map(np);
1820 if (tex !=
nullptr) {
1821 sampler = tex->get_default_sampler();
1826 if (spec._stage == 0) {
1828 <<
"Shader input " << *parent
1829 <<
" has no member named " << basename <<
".\n";
1837 if (spec._stage == 0) {
1839 <<
"Shader input " << *spec._name <<
" is not present.\n";
1845 return _target_shader->get_shader_input_texture(spec._name, &sampler);
1849 case Shader::STO_stage_i:
1854 _target_rs->get_attrib_def(texattrib);
1865 case Shader::STO_light_i_shadow_map:
1868 _target_rs->get_attrib_def(target_light);
1873 if (spec._stage >= 0 && (
size_t)spec._stage < num_lights) {
1875 nassertr(!light.
is_empty(),
nullptr);
1877 nassertr(light_obj !=
nullptr,
nullptr);
1881 if (lln !=
nullptr && lln->_shadow_caster) {
1882 tex = get_shadow_map(light);
1884 tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type);
1887 if (tex !=
nullptr) {
1888 sampler = tex->get_default_sampler();
1893 PT(
Texture) tex = get_dummy_shadow_map((Texture::TextureType)spec._desired_type);
1894 if (tex !=
nullptr) {
1895 sampler = tex->get_default_sampler();
1902 case Shader::STO_ff_stage_i:
1907 _target_rs->get_attrib_def(texattrib);
1918 case Shader::STO_stage_modulate_i:
1921 if (_target_rs->get_attrib(texattrib)) {
1925 TextureStage::Mode mode = stage->
get_mode();
1927 if (mode == TextureStage::M_modulate ||
1928 mode == TextureStage::M_modulate_glow ||
1929 mode == TextureStage::M_modulate_gloss) {
1930 if (si++ == spec._stage) {
1941 case Shader::STO_stage_add_i:
1944 if (_target_rs->get_attrib(texattrib)) {
1948 TextureStage::Mode mode = stage->
get_mode();
1950 if (mode == TextureStage::M_add) {
1951 if (si++ == spec._stage) {
1960 if (default_add_tex ==
nullptr) {
1962 tex->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_luminance);
1963 tex->set_clear_color(LColor(0, 0, 0, 1));
1964 default_add_tex = std::move(tex);
1966 return default_add_tex;
1970 case Shader::STO_stage_normal_i:
1973 if (_target_rs->get_attrib(texattrib)) {
1977 TextureStage::Mode mode = stage->
get_mode();
1979 if (mode == TextureStage::M_normal ||
1980 mode == TextureStage::M_normal_height) {
1981 if (si++ == spec._stage) {
1990 if (default_normal_height_tex ==
nullptr) {
1992 tex->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_rgba);
1993 tex->set_clear_color(LColor(0.5, 0.5, 1, 0));
1994 default_normal_height_tex = std::move(tex);
1996 return default_normal_height_tex;
2000 case Shader::STO_stage_gloss_i:
2003 if (_target_rs->get_attrib(texattrib)) {
2007 TextureStage::Mode mode = stage->
get_mode();
2009 if (mode == TextureStage::M_gloss ||
2010 mode == TextureStage::M_modulate_gloss ||
2011 mode == TextureStage::M_normal_gloss) {
2012 if (si++ == spec._stage) {
2023 case Shader::STO_stage_height_i:
2026 if (_target_rs->get_attrib(texattrib)) {
2030 TextureStage::Mode mode = stage->
get_mode();
2032 if (mode == TextureStage::M_height ||
2033 mode == TextureStage::M_normal_height) {
2034 if (si++ == spec._stage) {
2043 if (default_normal_height_tex ==
nullptr) {
2045 tex->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_rgba);
2046 tex->set_clear_color(LColor(0.5, 0.5, 1, 0));
2047 default_normal_height_tex = std::move(tex);
2049 return default_normal_height_tex;
2053 case Shader::STO_stage_selector_i:
2056 if (_target_rs->get_attrib(texattrib)) {
2060 TextureStage::Mode mode = stage->
get_mode();
2062 if (mode == TextureStage::M_selector) {
2063 if (si++ == spec._stage) {
2074 case Shader::STO_stage_emission_i:
2077 if (_target_rs->get_attrib(texattrib)) {
2081 TextureStage::Mode mode = stage->
get_mode();
2083 if (mode == TextureStage::M_emission) {
2084 if (si++ == spec._stage) {
2096 nassertr(
false,
nullptr);
2108 return (_target_shader->get_shader_input_ptr(spec._arg));
2117 _current_display_region = dr->get_object();
2120 _effective_incomplete_render = _incomplete_render && _current_display_region->get_incomplete_render();
2122 _stereo_buffer_mask = ~0;
2127 switch (output_channel) {
2129 output_channel = Lens::SC_right;
2132 case Lens::SC_right:
2133 output_channel = Lens::SC_left;
2141 switch (output_channel) {
2144 if (_current_properties->is_stereo()) {
2149 case Lens::SC_right:
2151 if (_current_properties->is_stereo()) {
2157 case Lens::SC_stereo:
2158 _color_write_mask = ColorWriteAttrib::C_all;
2181 reissue_transforms();
2184 _state_rs = RenderState::make_empty();
2185 _state_mask.
clear();
2195 nassertv(_engine !=
nullptr);
2197 DCAST_INTO_V(win, window);
2220 calc_projection_mat(
const Lens *lens) {
2221 if (lens ==
nullptr) {
2229 return TransformState::make_identity();
2242 _prepared_objects->begin_frame(
this, current_thread);
2249 _state_rs = RenderState::make_empty();
2250 _state_mask.
clear();
2256 if (_last_query_frame < frame) {
2257 _last_query_frame = frame;
2258 _timer_queries_pcollector.clear_level();
2265 if (_timer_queries_active) {
2268 issue_timer_query(0x8000);
2269 issue_timer_query(0x0000);
2274 return !_needs_reset;
2305 _scene_setup = _scene_null;
2311 for (i = 0; i < _num_lights_enabled; ++i) {
2312 enable_light(i,
false);
2314 _num_lights_enabled = 0;
2317 for (i = 0; i < _num_clip_planes_enabled; ++i) {
2318 enable_clip_plane(i,
false);
2320 _num_clip_planes_enabled = 0;
2323 _state_rs = RenderState::make_empty();
2324 _state_mask.
clear();
2333 _prepared_objects->end_frame(current_thread);
2336 _data_transferred_pcollector.flush_level();
2338 _primitive_batches_pcollector.flush_level();
2339 _primitive_batches_tristrip_pcollector.flush_level();
2340 _primitive_batches_trifan_pcollector.flush_level();
2341 _primitive_batches_tri_pcollector.flush_level();
2342 _primitive_batches_patch_pcollector.flush_level();
2343 _primitive_batches_other_pcollector.flush_level();
2344 _vertices_tristrip_pcollector.flush_level();
2345 _vertices_trifan_pcollector.flush_level();
2346 _vertices_tri_pcollector.flush_level();
2347 _vertices_patch_pcollector.flush_level();
2348 _vertices_other_pcollector.flush_level();
2350 _state_pcollector.flush_level();
2351 _texture_state_pcollector.flush_level();
2352 _transform_state_pcollector.flush_level();
2353 _draw_primitive_pcollector.flush_level();
2356 _prepared_objects->_graphics_memory_lru.begin_epoch();
2370 PStatClient *client = PStatClient::get_global_pstats();
2372 if (!client->client_is_connected()) {
2373 _timer_queries_active =
false;
2377 if (!_timer_queries_active) {
2378 if (pstats_gpu_timing && _supports_timer_query) {
2380 _timer_queries_active =
true;
2388 if (_pstats_gpu_thread == -1) {
2391 PStatThread gpu_thread(client, _pstats_gpu_thread);
2395 if (!_pending_timer_queries.empty()) {
2396 int count = _pending_timer_queries.size();
2403 if (_last_num_queried > 0) {
2406 int i = std::min(_last_num_queried, count) - 1;
2408 if (_pending_timer_queries[i]->is_answer_ready()) {
2410 while (i < count - 1) {
2411 if (!_pending_timer_queries[++i]->is_answer_ready()) {
2419 if (_pending_timer_queries[--i]->is_answer_ready()) {
2430 int step = count / 2;
2431 int i = first + step;
2432 if (_pending_timer_queries[i]->is_answer_ready()) {
2445 _last_num_queried = first;
2447 for (
int i = 0; i < first; ++i) {
2450 double time_data = query->get_timestamp();
2452 if (query->_pstats_index == _command_latency_pcollector.get_index()) {
2455 cdef = client->get_collector_ptr(query->_pstats_index)->get_def(client, query->_pstats_index);
2456 _pstats_gpu_data.add_level(query->_pstats_index, time_data * cdef->_factor);
2458 }
else if (query->_pstats_index & 0x8000) {
2459 _pstats_gpu_data.add_stop(query->_pstats_index & 0x7fff, time_data);
2462 _pstats_gpu_data.add_start(query->_pstats_index & 0x7fff, time_data);
2468 if (query->_pstats_index == 0x8000) {
2470 _pstats_gpu_data.clear();
2477 _pending_timer_queries.erase(
2478 _pending_timer_queries.begin(),
2479 _pending_timer_queries.begin() + first
2481 _timer_queries_pcollector.add_level_now(first);
2504 begin_decal_base_first() {
2507 if (decal_base_first ==
nullptr) {
2508 decal_base_first = RenderState::make
2509 (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
2510 RenderState::get_max_priority());
2512 return decal_base_first;
2522 begin_decal_nested() {
2526 if (decal_nested ==
nullptr) {
2527 decal_nested = RenderState::make
2528 (DepthWriteAttrib::make(DepthWriteAttrib::M_off),
2529 RenderState::get_max_priority());
2531 return decal_nested;
2545 begin_decal_base_second() {
2550 if (decal_base_second ==
nullptr) {
2551 decal_base_second = RenderState::make
2552 (ColorWriteAttrib::make(ColorWriteAttrib::C_off),
2556 RenderState::get_max_priority());
2558 return decal_base_second;
2578 _data_reader = data_reader;
2582 return _data_reader->has_vertex() || (_target_shader && _target_shader->has_shader());
2681 _data_reader =
nullptr;
2689 _needs_reset =
false;
2692 _state_rs = RenderState::make_empty();
2693 _target_rs =
nullptr;
2694 _state_mask.
clear();
2695 _internal_transform = _cs_transform;
2697 _scene_setup = _scene_null;
2699 _color_write_mask = ColorWriteAttrib::C_all;
2701 _has_scene_graph_color =
false;
2702 _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2703 _transform_stale =
true;
2704 _color_blend_involves_color_scale =
false;
2705 _texture_involves_color_scale =
false;
2706 _vertex_colors_enabled =
true;
2707 _lighting_enabled =
false;
2708 _num_lights_enabled = 0;
2709 _num_clip_planes_enabled = 0;
2710 _clip_planes_enabled =
false;
2712 _color_scale_enabled =
false;
2713 _current_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
2714 _has_texture_alpha_scale =
false;
2716 _has_material_force_color =
false;
2717 _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2718 _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
2720 _tex_gen_modifies_mat =
false;
2721 _last_max_stage_index = 0;
2771 get_cs_transform_for(CoordinateSystem cs)
const {
2772 if (_coordinate_system == cs) {
2774 return _cs_transform;
2776 }
else if (_internal_coordinate_system == CS_default ||
2777 _internal_coordinate_system == cs) {
2778 return TransformState::make_identity();
2781 return TransformState::make_mat
2782 (LMatrix4::convert_mat(cs, _internal_coordinate_system));
2793 get_cs_transform()
const {
2794 return _cs_transform;
2801 void GraphicsStateGuardian::
2802 do_issue_clip_plane() {
2803 int num_enabled = 0;
2804 int num_on_planes = 0;
2807 _target_rs->get_attrib_def(ClipPlaneAttrib::get_class_slot());
2809 if (target_clip_plane !=
nullptr) {
2810 CPT(
ClipPlaneAttrib) new_plane = target_clip_plane->filter_to_max(_max_clip_planes);
2813 for (
int li = 0; li < num_on_planes; li++) {
2814 NodePath plane = new_plane->get_on_plane(li);
2817 DCAST_INTO_V(plane_node, plane.
node());
2820 if (!_clip_planes_enabled) {
2821 enable_clip_planes(
true);
2822 _clip_planes_enabled =
true;
2825 enable_clip_plane(num_enabled,
true);
2826 if (num_enabled == 0) {
2827 begin_bind_clip_planes();
2830 bind_clip_plane(plane, num_enabled);
2837 for (i = num_enabled; i < _num_clip_planes_enabled; ++i) {
2838 enable_clip_plane(i,
false);
2840 _num_clip_planes_enabled = num_enabled;
2843 if (num_enabled == 0) {
2844 if (_clip_planes_enabled) {
2845 enable_clip_planes(
false);
2846 _clip_planes_enabled =
false;
2849 end_bind_clip_planes();
2864 _target_rs->get_attrib_def(ColorAttrib::get_class_slot());
2867 case ColorAttrib::T_flat:
2870 _scene_graph_color = target_color->
get_color();
2871 _has_scene_graph_color =
true;
2872 _vertex_colors_enabled =
false;
2875 case ColorAttrib::T_off:
2878 _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2879 _has_scene_graph_color =
false;
2880 _vertex_colors_enabled =
false;
2883 case ColorAttrib::T_vertex:
2886 _scene_graph_color.set(1.0f, 1.0f, 1.0f, 1.0f);
2887 _has_scene_graph_color =
false;
2888 _vertex_colors_enabled =
true;
2892 if (_color_scale_via_lighting) {
2893 _state_mask.
clear_bit(LightAttrib::get_class_slot());
2894 _state_mask.
clear_bit(MaterialAttrib::get_class_slot());
2896 determine_light_color_scale();
2903 void GraphicsStateGuardian::
2904 do_issue_color_scale() {
2907 if (_has_texture_alpha_scale) {
2908 _state_mask.
clear_bit(TextureAttrib::get_class_slot());
2912 _target_rs->get_attrib_def(ColorScaleAttrib::get_class_slot());
2914 _color_scale_enabled = target_color_scale->
has_scale();
2915 _current_color_scale = target_color_scale->
get_scale();
2916 _has_texture_alpha_scale =
false;
2918 if (_color_blend_involves_color_scale) {
2919 _state_mask.
clear_bit(TransparencyAttrib::get_class_slot());
2921 if (_texture_involves_color_scale) {
2922 _state_mask.
clear_bit(TextureAttrib::get_class_slot());
2924 if (_color_scale_via_lighting) {
2925 _state_mask.
clear_bit(LightAttrib::get_class_slot());
2926 _state_mask.
clear_bit(MaterialAttrib::get_class_slot());
2928 determine_light_color_scale();
2931 if (_alpha_scale_via_texture && !_has_scene_graph_color &&
2935 _state_mask.
clear_bit(TextureAttrib::get_class_slot());
2936 _state_mask.
clear_bit(TexMatrixAttrib::get_class_slot());
2938 _has_texture_alpha_scale =
true;
2958 LColor cur_ambient_light(0.0f, 0.0f, 0.0f, 0.0f);
2961 int num_enabled = 0;
2962 bool any_on_lights =
false;
2965 _target_rs->get_attrib_def(target_light);
2967 if (display_cat.is_spam()) {
2969 <<
"do_issue_light: " << target_light <<
"\n";
2971 if (target_light !=
nullptr) {
2976 for (
size_t li = 0; li < filtered_lights; ++li) {
2980 nassertv(light_obj !=
nullptr);
2983 if (!_lighting_enabled) {
2984 enable_lighting(
true);
2985 _lighting_enabled =
true;
2988 const LColor &color = light_obj->
get_color();
2990 if (color[0] != 0.0 || color[1] != 0.0 || color[2] != 0.0) {
2991 enable_light(num_enabled,
true);
2992 if (num_enabled == 0) {
2993 begin_bind_lights();
2996 light_obj->bind(
this, light, num_enabled);
3002 for (i = num_enabled; i < _num_lights_enabled; ++i) {
3003 enable_light(i,
false);
3005 _num_lights_enabled = num_enabled;
3008 if (!any_on_lights) {
3009 if (_color_scale_via_lighting && (_has_material_force_color || _light_color_scale != LVecBase4(1.0f, 1.0f, 1.0f, 1.0f))) {
3011 if (!_lighting_enabled) {
3012 enable_lighting(
true);
3013 _lighting_enabled =
true;
3015 set_ambient_light(LColor(1.0f, 1.0f, 1.0f, 1.0f));
3018 if (_lighting_enabled) {
3019 enable_lighting(
false);
3020 _lighting_enabled =
false;
3026 if (!_lighting_enabled) {
3027 enable_lighting(
true);
3028 _lighting_enabled =
true;
3031 set_ambient_light(target_light->get_ambient_contribution());
3034 if (num_enabled != 0) {
3096 void GraphicsStateGuardian::
3097 init_frame_pstats() {
3099 _data_transferred_pcollector.clear_level();
3100 _vertex_buffer_switch_pcollector.clear_level();
3101 _index_buffer_switch_pcollector.clear_level();
3103 _primitive_batches_pcollector.clear_level();
3104 _primitive_batches_tristrip_pcollector.clear_level();
3105 _primitive_batches_trifan_pcollector.clear_level();
3106 _primitive_batches_tri_pcollector.clear_level();
3107 _primitive_batches_patch_pcollector.clear_level();
3108 _primitive_batches_other_pcollector.clear_level();
3109 _vertices_tristrip_pcollector.clear_level();
3110 _vertices_trifan_pcollector.clear_level();
3111 _vertices_tri_pcollector.clear_level();
3112 _vertices_patch_pcollector.clear_level();
3113 _vertices_other_pcollector.clear_level();
3115 _state_pcollector.clear_level();
3116 _transform_state_pcollector.clear_level();
3117 _texture_state_pcollector.clear_level();
3127 create_gamma_table (PN_stdfloat gamma,
unsigned short *red_table,
unsigned short *green_table,
unsigned short *blue_table) {
3135 for (i = 0; i < 256; i++) {
3138 PN_stdfloat gamma_correction;
3140 x = ((double) i / 255.0);
3141 gamma_correction = 1.0 / gamma;
3142 x = pow (x, (
double) gamma_correction);
3148 red_table [i] = (int)g;
3149 green_table [i] = (int)g;
3150 blue_table [i] = (int)g;
3159 void GraphicsStateGuardian::
3160 reissue_transforms() {
3168 void GraphicsStateGuardian::
3169 enable_lighting(
bool enable) {
3177 void GraphicsStateGuardian::
3178 set_ambient_light(
const LColor &color) {
3186 void GraphicsStateGuardian::
3187 enable_light(
int light_id,
bool enable) {
3198 void GraphicsStateGuardian::
3199 begin_bind_lights() {
3208 void GraphicsStateGuardian::
3217 void GraphicsStateGuardian::
3218 enable_clip_planes(
bool enable) {
3226 void GraphicsStateGuardian::
3227 enable_clip_plane(
int plane_id,
bool enable) {
3238 void GraphicsStateGuardian::
3239 begin_bind_clip_planes() {
3247 void GraphicsStateGuardian::
3248 bind_clip_plane(
const NodePath &plane,
int plane_id) {
3257 void GraphicsStateGuardian::
3258 end_bind_clip_planes() {
3264 void GraphicsStateGuardian::
3265 determine_target_texture() {
3267 _target_rs->get_attrib_def(TextureAttrib::get_class_slot());
3269 _target_rs->get_attrib_def(TexGenAttrib::get_class_slot());
3271 nassertv(target_texture !=
nullptr &&
3272 target_tex_gen !=
nullptr);
3273 _target_texture = target_texture;
3274 _target_tex_gen = target_tex_gen;
3276 if (_has_texture_alpha_scale) {
3280 _target_texture = DCAST(
TextureAttrib, _target_texture->add_on_stage(stage, texture));
3281 _target_tex_gen = DCAST(
TexGenAttrib, _target_tex_gen->add_stage
3282 (stage, TexGenAttrib::M_constant, LTexCoord3(_current_color_scale[3], 0.0f, 0.0f)));
3286 _target_texture = _target_texture->filter_to_max(max_texture_stages);
3287 nassertv(_target_texture->get_num_on_stages() <= max_texture_stages);
3293 void GraphicsStateGuardian::
3294 determine_target_shader() {
3295 if (_target_rs->_generated_shader !=
nullptr) {
3296 _target_shader = (
const ShaderAttrib *)_target_rs->_generated_shader.p();
3299 _target_rs->get_attrib_def(ShaderAttrib::get_class_slot());
3306 void GraphicsStateGuardian::
3315 void GraphicsStateGuardian::
3322 _closing_gsg =
true;
3324 if (display_cat.is_debug()) {
3326 <<
this <<
" close_gsg " << get_type() <<
"\n";
3340 _prepared_objects.clear();
3342 _pending_timer_queries.clear();
3353 void GraphicsStateGuardian::
3354 panic_deactivate() {
3357 <<
"Deactivating " << get_type() <<
".\n";
3359 throw_event(
"panic-deactivate-gsg",
this);
3368 void GraphicsStateGuardian::
3369 determine_light_color_scale() {
3370 if (_has_scene_graph_color) {
3374 _has_material_force_color =
true;
3375 _material_force_color = _scene_graph_color;
3376 _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3377 if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3378 _material_force_color.set(_scene_graph_color[0] * _current_color_scale[0],
3379 _scene_graph_color[1] * _current_color_scale[1],
3380 _scene_graph_color[2] * _current_color_scale[2],
3381 _scene_graph_color[3] * _current_color_scale[3]);
3384 }
else if (!_vertex_colors_enabled) {
3388 _has_material_force_color =
true;
3389 _material_force_color.set(1.0f, 1.0f, 1.0f, 1.0f);
3390 _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3391 if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3392 _material_force_color.componentwise_mult(_current_color_scale);
3398 _has_material_force_color =
false;
3399 _light_color_scale.set(1.0f, 1.0f, 1.0f, 1.0f);
3400 if (!_color_blend_involves_color_scale && _color_scale_enabled) {
3401 _light_color_scale = _current_color_scale;
3412 if (state ==
nullptr) {
3413 state = RenderState::make(LightAttrib::make_all_off());
3422 get_unclipped_state() {
3424 if (state ==
nullptr) {
3425 state = RenderState::make(ClipPlaneAttrib::make_all_off());
3434 get_untextured_state() {
3436 if (state ==
nullptr) {
3437 state = RenderState::make(TextureAttrib::make_off());
3451 nassertr(_loader !=
nullptr,
nullptr);
3454 if (_current_display_region !=
nullptr) {
3455 priority = _current_display_region->get_texture_reload_priority();
3458 string task_name = string(
"reload:") + tc->
get_texture()->get_name();
3464 for (
size_t ti = 0; ti < num_tasks; ++ti) {
3466 if (task->
is_exact_type(TextureReloadRequest::get_class_type()) &&
3479 _supports_compressed_texture);
3480 request->set_priority(priority);
3481 _loader->load_async(request);
3493 bool is_point = node->
is_of_type(PointLight::get_class_type());
3494 nassertr(node->
is_of_type(DirectionalLight::get_class_type()) ||
3495 node->
is_of_type(Spotlight::get_class_type()) ||
3499 if (light ==
nullptr || !light->_shadow_caster) {
3502 if (node->
is_of_type(PointLight::get_class_type())) {
3503 return get_dummy_shadow_map(Texture::TT_cube_map);
3505 return get_dummy_shadow_map(Texture::TT_2d_texture);
3510 nassertr(light->_shadow_map !=
nullptr,
nullptr);
3513 if (light->_sbuffers.count(
this) != 0) {
3515 return light->_shadow_map;
3518 if (display_cat.is_debug()) {
3520 <<
"Constructing shadow buffer for light '" << light->get_name()
3521 <<
"', size=" << light->_sb_size[0] <<
"x" << light->_sb_size[1]
3522 <<
", sort=" << light->_sb_sort <<
"\n";
3525 if (host ==
nullptr) {
3526 nassertr(_current_display_region !=
nullptr,
nullptr);
3527 host = _current_display_region->get_window();
3529 nassertr(host !=
nullptr,
nullptr);
3532 GraphicsOutput *sbuffer = make_shadow_buffer(light, light->_shadow_map,
3537 for (
int i = 0; i < 6; ++i) {
3540 dr->set_target_tex_page(i);
3541 dr->set_camera(light_np);
3542 dr->set_clear_depth_active(
true);
3547 dr->set_clear_depth_active(
true);
3550 light->_sbuffers[
this] = sbuffer;
3551 return light->_shadow_map;
3559 get_dummy_shadow_map(Texture::TextureType texture_type)
const {
3560 if (texture_type != Texture::TT_cube_map) {
3562 if (dummy_2d ==
nullptr) {
3563 dummy_2d =
new Texture(
"dummy-shadow-2d");
3564 dummy_2d->setup_2d_texture(1, 1, Texture::T_unsigned_byte, Texture::F_depth_component);
3565 dummy_2d->set_clear_color(1);
3568 dummy_2d->set_minfilter(SamplerState::FT_shadow);
3569 dummy_2d->set_magfilter(SamplerState::FT_shadow);
3571 dummy_2d->set_minfilter(SamplerState::FT_linear);
3572 dummy_2d->set_magfilter(SamplerState::FT_linear);
3577 static PT(
Texture) dummy_cube;
3578 if (dummy_cube ==
nullptr) {
3579 dummy_cube =
new Texture(
"dummy-shadow-cube");
3580 dummy_cube->setup_cube_map(1, Texture::T_unsigned_byte, Texture::F_depth_component);
3581 dummy_cube->set_clear_color(1);
3583 dummy_cube->set_minfilter(SamplerState::FT_linear);
3584 dummy_cube->set_magfilter(SamplerState::FT_linear);
3596 bool is_point = light->
is_of_type(PointLight::get_class_type());
3600 fbp.set_depth_bits(shadow_depth_bits);
3603 int flags = GraphicsPipe::BF_refuse_window;
3605 flags |= GraphicsPipe::BF_size_square;
3612 light->get_name(), light->_sb_sort, fbp, props, flags,
this, host);
3614 if (sbuffer !=
nullptr) {
3615 sbuffer->
add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, GraphicsOutput::RTP_depth);
3628 state->get_attrib_def(shader_attrib);
3631 if (_shader_generator ==
nullptr) {
3632 if (!_supports_basic_shaders) {
3637 if (state->_generated_shader ==
nullptr ||
3638 state->_generated_shader_seq != _generated_shader_seq) {
3644 state->get_attrib_def(sattr);
3645 if (sattr->get_flag(ShaderAttrib::F_hardware_skinning)) {
3650 state->_generated_shader = _shader_generator->synthesize_shader(state, spec);
3651 state->_generated_shader_seq = _generated_shader_seq;
3728 operator << (std::ostream &out, GraphicsStateGuardian::ShaderModel sm) {
3729 static const char *sm_strings[] = {
"none",
"1.1",
"2.0",
"2.x",
"3.0",
"4.0",
"5.0",
"5.1"};
3730 nassertr(sm >= 0 && sm <= GraphicsStateGuardian::SM_51, out);
3731 out << sm_strings[sm];
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
A light source that seems to illuminate all points in space at once.
This class represents a thread-safe handle to a promised future result of an asynchronous operation,...
A list of tasks, for instance as returned by some of the AsyncTaskManager query functions.
get_num_tasks
Returns the number of AsyncTasks in the collection.
get_task
Returns the nth AsyncTask in the collection.
A class to manage a loose queue of isolated tasks, which can be performed either synchronously (in th...
This class represents a concrete task performed by an AsyncManager.
get_priority
Returns the task's current priority value.
set_priority
Specifies a priority value for this task.
void clear_bit(int index)
Sets the nth bit off.
void clear()
Sets all the bits in the BitMask off.
This is a base class for those kinds of SavedContexts that occupy an easily-measured (and substantial...
This is a const pointer to an InternalName, and should be used in lieu of a CPT(InternalName) in func...
This functions similarly to a LightAttrib.
get_on_plane
Returns the nth plane enabled by the attribute, sorted in render order.
get_num_on_planes
Returns the number of planes that are enabled by the attribute.
get_frame_time
Returns the time in seconds as of the last time tick() was called (typically, this will be as of the ...
get_dt
Returns the elapsed time for the previous frame: the number of seconds elapsed between the last two c...
get_frame_count
Returns the number of times tick() has been called since the ClockObject was created,...
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Indicates what color should be applied to renderable geometry.
get_color
If the type is T_flat or T_off, this returns the color that will be applied to geometry.
get_color_type
Returns the type of color specified by this ColorAttrib.
Applies a scale to colors in the scene graph and on vertices.
bool has_alpha_scale() const
Returns true if the ColorScaleAttrib has a non-identity scale in the alpha component (ignoring RGB),...
has_scale
Returns true if the ColorScaleAttrib has a non-identity scale, false otherwise (in which case it migh...
get_scale
Returns the scale to be applied to colors.
bool is_identity() const
Returns true if the ColorScaleAttrib is an identity attrib, false if it is either an off attrib or it...
A light shining from infinitely far away in a particular direction, like sunlight.
get_direction
Returns the direction in which the light is aimed.
get_specular_color
Returns the color of specular highlights generated by the light.
Encapsulates the data from a DisplayRegion, pre-fetched for one stage of the pipeline.
GraphicsOutput * get_window() const
Returns the GraphicsOutput that this DisplayRegion is ultimately associated with, or NULL if no windo...
int get_tex_view_offset()
Returns the current texture view offset for this DisplayRegion.
Lens::StereoChannel get_stereo_channel() const
Returns whether the DisplayRegion is specified as the left or right channel of a stereo pair,...
A rectangular subregion within a window for rendering into.
set_camera
Sets the camera that is associated with this DisplayRegion.
set_lens_index
Sets the lens index, allows for multiple lenses to be attached to a camera.
This is a base class for GraphicsWindow (actually, GraphicsOutput) and DisplayRegion,...
Applies a Fog to the geometry at and below this node.
get_fog
If the FogAttrib is not an 'off' FogAttrib, returns the fog that is associated.
Specifies how atmospheric fog effects are applied to geometry.
get_color
Returns the color of the fog.
get_exp_density
Returns the density of the fog for exponential calculations.
void get_linear_range(PN_stdfloat &onset, PN_stdfloat &opaque)
Retrieves the current onset and offset ranges.
A container for the various kinds of properties we might ask to have on a graphics frameBuffer before...
int get_buffer_mask() const
Converts the non-aux bitplanes of the framebuffer into a RenderBuffer::Type.
This is a special class object that holds all the information returned by a particular GSG to indicat...
Objects of this class are used to convert vertex data from a Geom into a format suitable for passing ...
static void unregister_mungers_for_gsg(GraphicsStateGuardianBase *gsg)
Removes all the mungers from the registry that are associated with the indicated GSG.
Encapsulates the data from a Geom, pre-fetched for one stage of the pipeline.
Encapsulates the data from a GeomPrimitive, pre-fetched for one stage of the pipeline.
This is an abstract base class for a family of classes that represent the fundamental geometry primit...
This object describes how the vertex animation, if any, represented in a GeomVertexData is encoded.
void set_hardware(int num_transforms, bool indexed_transforms)
Specifies that vertex animation is to be performed by the graphics hardware (or at least by the graph...
This is the data for one array of a GeomVertexData structure.
Encapsulates the data from a GeomVertexData, pre-fetched for one stage of the pipeline.
A container for geometry primitives.
This class is the main interface to controlling the render process.
bool remove_window(GraphicsOutput *window)
Removes the indicated window or offscreen buffer from the set of windows that will be processed when ...
GraphicsOutput * make_output(GraphicsPipe *pipe, const std::string &name, int sort, const FrameBufferProperties &fb_prop, const WindowProperties &win_prop, int flags, GraphicsStateGuardian *gsg=nullptr, GraphicsOutput *host=nullptr)
Creates a new window (or buffer) and returns it.
An abstract base class for GraphicsOutput, for all the usual reasons.
This is a base class for the various different classes that represent the result of a frame of render...
void add_render_texture(Texture *tex, RenderTextureMode mode, RenderTexturePlane bitplane=RTP_COUNT)
Creates a new Texture object, suitable for rendering the contents of this buffer into,...
DisplayRegion * make_mono_display_region()
Creates a new DisplayRegion that covers the entire window.
unsigned int get_right_eye_color_mask() const
Returns the color mask in effect when rendering a right-eye view in red_blue stereo mode.
get_swap_eyes
Returns the current setting of the "swap eyes" flag.
unsigned int get_left_eye_color_mask() const
Returns the color mask in effect when rendering a left-eye view in red_blue stereo mode.
An object to create GraphicsOutputs that share a particular 3-D API.
static void remove_gsg(GraphicsStateGuardianBase *gsg)
Called by a GSG destructor to remove a GSG from the available list.
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,...
virtual bool draw_points(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected points.
virtual bool draw_trifans(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle fans.
virtual void clear_before_callback()
Resets any non-standard graphics state that might give a callback apoplexy.
get_pipe
Returns the graphics pipe on which this GSG was created.
virtual bool depth_offset_decals()
Returns true if this GSG can implement decals using a DepthOffsetAttrib, or false if that is unreliab...
get_gamma
Get the current gamma setting.
virtual bool begin_draw_primitives(const GeomPipelineReader *geom_reader, const GeomVertexDataPipelineReader *data_reader, bool force)
Called before a sequence of draw_primitive() functions are called, this should prepare the vertex dat...
virtual bool update_texture(TextureContext *tc, bool force)
Ensures that the current Texture data is refreshed onto the GSG.
set_scene
Sets the SceneSetup object that indicates the initial camera position, etc.
GraphicsEngine * get_engine() const
Returns the graphics engine that created this GSG.
static TextureStage * get_alpha_scale_texture_stage()
Returns the TextureStage that will be used to apply an alpha scale, if get_alpha_scale_via_texture() ...
virtual TextureContext * prepare_texture(Texture *tex, int view)
Creates whatever structures the GSG requires to represent the texture internally, and returns a newly...
get_supports_multisample
Returns true if this particular GSG supports using the multisample bits to provide antialiasing,...
virtual bool draw_triangles(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected triangles.
get_driver_version_minor
Returns the minor version of the video driver.
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,...
virtual bool draw_lines(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected line segments.
virtual void release_shader_buffer(BufferContext *ibc)
Frees the resources previously allocated via a call to prepare_data(), including deleting the BufferC...
set_active
Sets the active flag associated with the GraphicsStateGuardian.
void traverse_prepared_textures(TextureCallback *func, void *callback_arg)
Calls the indicated function on all currently-prepared textures, or until the callback function retur...
get_flash_texture
Returns the current "flash texture", if any, or NULL if none.
virtual bool prepare_lens()
Makes the current lens (whichever lens was most recently specified with set_scene()) active,...
static void create_gamma_table(PN_stdfloat gamma, unsigned short *red_table, unsigned short *green_table, unsigned short *blue_table)
Create a gamma table.
virtual void clear_state_and_transform()
Forgets the current graphics state and current transform, so that the next call to set_state_and_tran...
get_driver_vendor
Returns the vendor of the video card driver.
virtual VertexBufferContext * prepare_vertex_buffer(GeomVertexArrayData *data)
Prepares the indicated buffer for retained-mode rendering.
virtual bool draw_patches(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of "patches", which can only be processed by a tessellation shader.
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.
virtual void prepare_display_region(DisplayRegionPipelineReader *dr)
Makes the specified DisplayRegion current.
get_driver_shader_version_minor
Returns the minor version of the shader model.
virtual void release_sampler(SamplerContext *sc)
Frees the resources previously allocated via a call to prepare_sampler(), including deleting the Samp...
get_prepared_objects
Returns the set of texture and geom objects that have been prepared with this GSG (and possibly other...
virtual void do_issue_light()
This implementation of do_issue_light() assumes we have a limited number of hardware lights available...
get_driver_renderer
Returns GL_Renderer.
void flush_timer_queries()
Called by the graphics engine on the draw thread to check the status of the running timer queries and...
virtual void release_vertex_buffer(VertexBufferContext *vbc)
Frees the resources previously allocated via a call to prepare_data(), including deleting the VertexB...
void do_issue_color()
This method is defined in the base class because it is likely that this functionality will be used fo...
const LMatrix4 * fetch_specified_part(Shader::ShaderMatInput input, InternalName *name, LMatrix4 &t, int index)
See fetch_specified_value.
virtual CoordinateSystem get_internal_coordinate_system() const
Returns the coordinate system used internally by the GSG.
virtual bool extract_texture_data(Texture *tex)
This method should only be called by the GraphicsEngine.
const LMatrix4 * fetch_specified_member(const NodePath &np, CPT_InternalName member, LMatrix4 &t)
Given a NodePath passed into a shader input that is a structure, fetches the value for the given memb...
get_driver_version_major
Returns major version of the video driver.
get_driver_shader_version_major
Returns the major version of the shader model.
virtual void release_geom(GeomContext *gc)
Frees the resources previously allocated via a call to prepare_geom(), including deleting the GeomCon...
get_supports_shadow_filter
Returns true if this particular GSG supports the filter mode FT_shadow for depth textures.
virtual SamplerContext * prepare_sampler(const SamplerState &sampler)
Creates whatever structures the GSG requires to represent the sampler internally, and returns a newly...
RenderBuffer get_render_buffer(int buffer_type, const FrameBufferProperties &prop)
Returns a RenderBuffer object suitable for operating on the requested set of buffers.
virtual void ensure_generated_shader(const RenderState *state)
Ensures that an appropriate shader has been generated for the given state.
get_max_texture_stages
Returns the maximum number of simultaneous textures that may be applied to geometry with multitexturi...
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...
virtual bool draw_lines_adj(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected line segments with adjacency information.
virtual bool has_extension(const std::string &extension) const
Returns true if the GSG implements the extension identified by the given string.
virtual bool draw_linestrips_adj(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of line strips with adjacency information.
virtual void end_scene()
Called between begin_frame() and end_frame() to mark the end of drawing commands for a "scene" (usual...
virtual void release_shader(ShaderContext *sc)
Releases the resources allocated by prepare_shader.
virtual GeomContext * prepare_geom(Geom *geom)
Prepares the indicated Geom for retained-mode rendering, by creating whatever structures are necessar...
virtual void reset()
Resets all internal state as if the gsg were newly created.
virtual int get_supported_geom_rendering() const
Returns the union of Geom::GeomRendering values that this particular GSG can support directly.
virtual void release_texture(TextureContext *tc)
Frees the resources previously allocated via a call to prepare_texture(), including deleting the Text...
get_driver_version
Returns driver version This has an implementation-defined meaning, and may be "" if the particular gr...
PN_stdfloat compute_distance_to(const LPoint3 &point) const
This function will compute the distance to the indicated point, assumed to be in eye coordinates,...
virtual void begin_occlusion_query()
Begins a new occlusion query.
const LMatrix4 * fetch_specified_value(Shader::ShaderMatSpec &spec, int altered)
The gsg contains a large number of useful matrices:
virtual IndexBufferContext * prepare_index_buffer(GeomPrimitive *data)
Prepares the indicated buffer for retained-mode rendering.
virtual void finish_decal()
Called during draw to clean up after decals are finished.
virtual bool draw_tristrips(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle strips.
get_scene
Returns the current SceneSetup object.
set_flash_texture
Sets the "flash texture".
virtual bool draw_linestrips(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of line strips.
virtual void set_state_and_transform(const RenderState *state, const TransformState *transform)
Simultaneously resets the render state and the transform state.
virtual bool get_supports_cg_profile(const std::string &name) const
Returns true if this particular GSG supports the specified Cg Shader Profile.
virtual bool draw_tristrips_adj(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of triangle strips with adjacency information.
virtual void clear(DrawableRegion *clearable)
Clears the framebuffer within the current DisplayRegion, according to the flags indicated by the give...
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...
set_coordinate_system
Changes the coordinate system in effect on this particular gsg.
virtual BufferContext * prepare_shader_buffer(ShaderBuffer *data)
Prepares the indicated buffer for retained-mode rendering.
virtual void remove_window(GraphicsOutputBase *window)
This is simply a transparent call to GraphicsEngine::remove_window().
virtual void restore_gamma()
Restore original gamma setting.
virtual bool draw_triangles_adj(const GeomPrimitivePipelineReader *reader, bool force)
Draws a series of disconnected triangles with adjacency information.
virtual void dispatch_compute(int size_x, int size_y, int size_z)
Dispatches a currently bound compute shader using the given work group counts.
virtual void release_index_buffer(IndexBufferContext *ibc)
Frees the resources previously allocated via a call to prepare_data(), including deleting the IndexBu...
void clear_flash_texture()
Resets the "flash texture", so that no textures will flash.
virtual void end_draw_primitives()
Called after a sequence of draw_primitive() functions are called, this should do whatever cleanup is ...
virtual ShaderContext * prepare_shader(Shader *shader)
Compile a vertex/fragment shader body.
virtual bool begin_scene()
Called between begin_frame() and end_frame() to mark the beginning of drawing commands for a "scene" ...
This is a special class object that holds all the information returned by a particular GSG to indicat...
Encodes a string name in a hash table, mapping it to a pointer.
get_basename
Return the name represented by just this particular InternalName object, ignoring its parents names.
get_name
Returns the complete name represented by the InternalName and all of its parents.
get_parent
Return the parent of this InternalName.
A node that contains a Lens.
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...
A base class for any number of different kinds of lenses, linear and otherwise.
virtual bool is_linear() const
Returns true if the lens represents a linear projection (e.g.
get_far
Returns the position of the far plane (or cylinder, sphere, whatever).
get_near
Returns the position of the near plane (or cylinder, sphere, whatever).
const LMatrix4 & get_projection_mat_inv(StereoChannel channel=SC_mono) const
Returns the matrix that transforms from a 2-d point on the film to a 3-d vector in space,...
PN_stdfloat get_hfov() const
Returns the horizontal component of fov only.
get_nodal_point
Returns the center point of the lens: the point from which the lens is viewing.
get_coordinate_system
Returns the coordinate system that all 3-d computations are performed within for this Lens.
const LVector3 & get_view_vector() const
Returns the axis along which the lens is facing.
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,...
Indicates which set of lights should be considered "on" to illuminate geometry at this level and belo...
bool has_any_on_light() const
Returns true if any light is turned on by the attrib, false otherwise.
size_t get_num_non_ambient_lights() const
Returns the number of non-ambient lights that are turned on by this attribute.
get_on_light
Returns the nth light turned on by the attribute, sorted in render order.
A derivative of Light and of Camera.
Similar to MutexHolder, but for a light reentrant mutex.
The abstract interface to all kinds of lights.
virtual PN_stdfloat get_exponent() const
For spotlights, returns the exponent that controls the amount of light falloff from the center of the...
virtual const LVecBase3 & get_attenuation() const
Returns the terms of the attenuation equation for the light.
get_color
Returns the basic color of the light.
virtual const LColor & get_specular_color() const
Returns the color of specular highlights generated by the light.
static Loader * get_global_ptr()
Returns a pointer to the global Loader.
Indicates which, if any, material should be applied to geometry.
bool is_off() const
Returns true if the MaterialAttrib is an 'off' MaterialAttrib, indicating that it should disable the ...
get_material
If the MaterialAttrib is not an 'off' MaterialAttrib, returns the material that is associated.
Defines the way an object appears in the presence of lighting.
get_ambient
Returns the ambient color setting, if it has been set.
get_emission
Returns the emission color setting, if it has been set.
get_base_color
Returns the base_color color setting, if it has been set.
get_refractive_index
Returns the index of refraction, or 1 if none has been set for this material.
get_specular
Returns the specular color setting, if it has been set.
get_metallic
Returns the metallic setting, if it has been set.
get_roughness
Returns the roughness previously specified by set_roughness.
get_shininess
Returns the shininess exponent of the material.
get_diffuse
Returns the diffuse color setting, if it has been set.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
bool is_empty() const
Returns true if the NodePath contains no nodes.
const LMatrix4 & get_mat() const
Returns the transform matrix that has been applied to the referenced node, or the identity matrix if ...
PandaNode * node() const
Returns the referenced node of the path.
const TransformState * get_transform(Thread *current_thread=Thread::get_current_thread()) const
Returns the complete transform object set on this node.
Returned from a GSG in response to begin_occlusion_query() .
Manages the communications to report statistics via a network connection to a remote PStatServer.
static bool is_connected()
Returns true if the client believes it is connected to a working PStatServer, false otherwise.
Defines the details about the Collectors: the name, the suggested color, etc.
A lightweight class that represents a single element that may be timed and/or counted via stats.
This is a special type of PStatTimer that also uses a timer query on the GSG to measure how long a ta...
A lightweight class that represents a single thread of execution to PStats.
void add_frame(const PStatFrameData &frame_data)
This is a slightly lower-level version of new_frame that also specifies the data to send for this fra...
A basic node of the scene graph or data graph.
virtual bool is_ambient_light() const
Returns true if this is an AmbientLight, false if it is not a light, or it is some other kind of ligh...
virtual Light * as_light()
Cross-casts the node to a Light pointer, if it is one of the four kinds of Light nodes,...
A node that contains a plane.
const LPlane & get_plane() const
Returns the plane represented by the PlaneNode.
int get_clip_effect() const
Returns the clip_effect bits for this clip plane.
A light originating from a single point in space, and shining in all directions.
get_specular_color
Returns the color of specular highlights generated by the light.
get_point
Returns the point in space at which the light is located.
get_attenuation
Returns the terms of the attenuation equation for the light.
A table of objects that are saved within the graphics context for reference by handle later.
Similar to MutexHolder, but for a reentrant mutex.
A RenderBuffer is an arbitrary subset of the various layers (depth buffer, color buffer,...
This represents a unique collection of RenderAttrib objects that correspond to a particular renderabl...
This is a special class object that holds a handle to the sampler state object given by the graphics ...
Represents a set of settings that indicate how a texture is sampled.
This object holds the camera position, etc., and other general setup information for rendering a part...
const Lens * get_lens() const
Returns the particular Lens used for rendering.
bool auto_shader() const
If true, then this ShaderAttrib does not contain an explicit shader - instead, it requests the automa...
This is a generic buffer object that lives in graphics memory.
The ShaderContext is meant to contain the compiled version of a shader string.
const Key & get_key(size_t n) const
Returns the key in the nth entry of the table.
int store(const Key &key, const Value &data)
Records the indicated key/data pair in the map.
const Value & get_data(size_t n) const
Returns the data in the nth entry of the table.
int find(const Key &key) const
Searches for the indicated key in the table.
bool remove(const Key &key)
Removes the indicated key and its associated data from the table.
void remove_element(size_t n)
Removes the nth entry from the table.
bool is_empty() const
Returns true if the table is empty; i.e.
size_t get_num_entries() const
Returns the number of active entries in the table.
A sphere light is like a point light, except that it represents a sphere with a radius,...
A light originating from a single point in space, and shining in a particular direction,...
get_specular_color
Returns the color of specular highlights generated by the light.
get_exponent
Returns the exponent that controls the amount of light falloff from the center of the spotlight.
get_attenuation
Returns the terms of the attenuation equation for the light.
Computes texture coordinates for geometry automatically based on vertex position and/or normal.
Applies a transform matrix to UV's before they are rendered.
Indicates the set of TextureStages and their associated Textures that should be applied to (or remove...
get_num_on_ff_stages
Returns the number of on-stages that are relevant to the classic fixed function pipeline.
get_num_on_stages
Returns the number of stages that are turned on by the attribute.
get_on_texture
Returns the texture associated with the indicated stage, or NULL if no texture is associated.
get_on_stage
Returns the nth stage turned on by the attribute, sorted in render order.
get_on_sampler
Returns the sampler associated with the indicated stage, or the one associated with its texture if no...
get_on_ff_stage
Returns the nth stage turned on by the attribute, sorted in render order, including only those releva...
This is a special class object that holds all the information returned by a particular GSG to indicat...
Texture * get_texture() const
Returns the pointer to the associated Texture object.
static Texture * get_alpha_scale_map()
Returns a standard Texture object that has been created with Texture::generate_alpha_scale_map().
This loader request will call Texture::get_ram_image() in a sub-thread, to force the texture's image ...
Defines the properties of a named stage of the multitexture pipeline.
get_color
return the color for this stage
get_tex_view_offset
Returns the current setting of the tex_view_offset.
get_mode
Return the mode of this stage.
Represents a texture object, which is typically a single 2-d image but may also represent a 1-d or 3-...
int get_pad_y_size() const
Returns size of the pad region.
get_y_size
Returns the height of the texture image in texels.
get_z_size
Returns the depth of the texture image in texels.
int get_pad_x_size() const
Returns size of the pad region.
int get_pad_z_size() const
Returns size of the pad region.
get_x_size
Returns the width of the texture image in texels.
A thread; that is, a lightweight process.
TypeHandle is the identifier used to differentiate C++ class types.
bool is_exact_type(TypeHandle handle) const
Returns true if the current object is the indicated type exactly.
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
This is a special class object that holds all the information returned by a particular GSG to indicat...
A container for the various kinds of properties we might ask to have on a graphics window before we o...
static WindowProperties size(const LVecBase2i &size)
Returns a WindowProperties structure with only the size specified.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PT(OcclusionQueryContext) GraphicsStateGuardian
Ends a previous call to begin_occlusion_query().
CPT(TransformState) GraphicsStateGuardian
Given a lens, this function calculates the appropriate projection matrix for this gsg.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.