diff --git a/doc/makepanda/makepanda71.vcproj b/doc/makepanda/makepanda71.vcproj index 0932878016..eb1ee2a0c4 100755 --- a/doc/makepanda/makepanda71.vcproj +++ b/doc/makepanda/makepanda71.vcproj @@ -17,8 +17,8 @@ ConfigurationType="0"> + BuildCommandLine="cd .. & makepanda\makepanda --everything" + Output="..\built\python\python.exe"/> diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 17b3ba40b5..aee7e3554e 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -757,6 +757,8 @@ reset() { _current_shader_context = (CLP(ShaderContext) *)NULL; _vertex_array_shader_expansion = (ShaderExpansion *)NULL; _vertex_array_shader_context = (CLP(ShaderContext) *)NULL; + _texture_binding_shader_expansion = (ShaderExpansion *)NULL; + _texture_binding_shader_context = (CLP(ShaderContext) *)NULL; // Count the max number of lights GLint max_lights; @@ -840,20 +842,20 @@ do_clear(const RenderBuffer &buffer) { int buffer_type = buffer._buffer_type; GLbitfield mask = 0; + set_state_and_transform(RenderState::make_empty(), _external_transform); + if (buffer_type & RenderBuffer::T_color) { GLP(ClearColor)(_color_clear_value[0], _color_clear_value[1], _color_clear_value[2], _color_clear_value[3]); mask |= GL_COLOR_BUFFER_BIT; - _target._color_write = AttribSlots::get_defaults()._color_write; set_draw_buffer(buffer); } if (buffer_type & RenderBuffer::T_depth) { GLP(ClearDepth)(_depth_clear_value); mask |= GL_DEPTH_BUFFER_BIT; - _target._depth_write = AttribSlots::get_defaults()._depth_write; } if (buffer_type & RenderBuffer::T_stencil) { @@ -886,20 +888,6 @@ do_clear(const RenderBuffer &buffer) { GLCAT.spam(false) << ")" << endl; } - if (_target._depth_write != _state._depth_write) { - do_issue_depth_write(); - _state._depth_write = _target._depth_write; - } - if ((_target._transparency != _state._transparency)|| - (_target._color_write != _state._color_write)|| - (_target._color_blend != _state._color_blend)) { - do_issue_blending(); - _state._transparency = _target._transparency; - _state._color_write = _target._color_write; - _state._color_blend = _target._color_blend; - } - _state_rs = 0; - GLP(Clear)(mask); report_my_gl_errors(); } @@ -1598,15 +1586,15 @@ draw_triangles(const GeomTriangles *primitive) { const unsigned char *client_pointer = setup_primitive(primitive); _glDrawRangeElements(GL_TRIANGLES, - primitive->get_min_vertex(), - primitive->get_max_vertex(), - primitive->get_num_vertices(), - get_numeric_type(primitive->get_index_type()), - client_pointer); + primitive->get_min_vertex(), + primitive->get_max_vertex(), + primitive->get_num_vertices(), + get_numeric_type(primitive->get_index_type()), + client_pointer); } else { GLP(DrawArrays)(GL_TRIANGLES, - primitive->get_first_vertex(), - primitive->get_num_vertices()); + primitive->get_first_vertex(), + primitive->get_num_vertices()); } } @@ -1642,17 +1630,17 @@ draw_tristrips(const GeomTristrips *primitive) { _vertices_tristrip_pcollector.add_level(primitive->get_num_vertices()); _primitive_batches_tristrip_pcollector.add_level(1); if (primitive->is_indexed()) { - const unsigned char *client_pointer = setup_primitive(primitive); - _glDrawRangeElements(GL_TRIANGLE_STRIP, - primitive->get_min_vertex(), - primitive->get_max_vertex(), - primitive->get_num_vertices(), - get_numeric_type(primitive->get_index_type()), - client_pointer); + const unsigned char *client_pointer = setup_primitive(primitive); + _glDrawRangeElements(GL_TRIANGLE_STRIP, + primitive->get_min_vertex(), + primitive->get_max_vertex(), + primitive->get_num_vertices(), + get_numeric_type(primitive->get_index_type()), + client_pointer); } else { - GLP(DrawArrays)(GL_TRIANGLE_STRIP, - primitive->get_first_vertex(), - primitive->get_num_vertices()); + GLP(DrawArrays)(GL_TRIANGLE_STRIP, + primitive->get_first_vertex(), + primitive->get_num_vertices()); } } else { @@ -1662,32 +1650,32 @@ draw_tristrips(const GeomTristrips *primitive) { _primitive_batches_tristrip_pcollector.add_level(ends.size()); if (primitive->is_indexed()) { - const unsigned char *client_pointer = setup_primitive(primitive); - int index_stride = primitive->get_index_stride(); - GeomVertexReader mins(primitive->get_mins(), 0); - GeomVertexReader maxs(primitive->get_maxs(), 0); - nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && - primitive->get_maxs()->get_num_rows() == (int)ends.size()); - - unsigned int start = 0; - for (size_t i = 0; i < ends.size(); i++) { - _vertices_tristrip_pcollector.add_level(ends[i] - start); - _glDrawRangeElements(GL_TRIANGLE_STRIP, - mins.get_data1i(), maxs.get_data1i(), - ends[i] - start, - get_numeric_type(primitive->get_index_type()), - client_pointer + start * index_stride); - start = ends[i] + 2; - } + const unsigned char *client_pointer = setup_primitive(primitive); + int index_stride = primitive->get_index_stride(); + GeomVertexReader mins(primitive->get_mins(), 0); + GeomVertexReader maxs(primitive->get_maxs(), 0); + nassertv(primitive->get_mins()->get_num_rows() == (int)ends.size() && + primitive->get_maxs()->get_num_rows() == (int)ends.size()); + + unsigned int start = 0; + for (size_t i = 0; i < ends.size(); i++) { + _vertices_tristrip_pcollector.add_level(ends[i] - start); + _glDrawRangeElements(GL_TRIANGLE_STRIP, + mins.get_data1i(), maxs.get_data1i(), + ends[i] - start, + get_numeric_type(primitive->get_index_type()), + client_pointer + start * index_stride); + start = ends[i] + 2; + } } else { - unsigned int start = 0; - int first_vertex = primitive->get_first_vertex(); - for (size_t i = 0; i < ends.size(); i++) { - _vertices_tristrip_pcollector.add_level(ends[i] - start); - GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start, - ends[i] - start); - start = ends[i] + 2; - } + unsigned int start = 0; + int first_vertex = primitive->get_first_vertex(); + for (size_t i = 0; i < ends.size(); i++) { + _vertices_tristrip_pcollector.add_level(ends[i] - start); + GLP(DrawArrays)(GL_TRIANGLE_STRIP, first_vertex + start, + ends[i] - start); + start = ends[i] + 2; + } } } } @@ -2453,12 +2441,7 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, // for GLP(ReadPixels)() to work // NOTE: reading the depth buffer is *much* slower than reading the // color buffer - _target._texture = AttribSlots::get_defaults()._texture; - if (_target._texture != _state._texture) { - do_issue_texture(); - _state._texture = _target._texture; - } - _state_rs = 0; + set_state_and_transform(RenderState::make_empty(), _external_transform); int xo, yo, w, h; dr->get_region_pixels(xo, yo, w, h); @@ -3086,7 +3069,7 @@ do_issue_blending() { } else { if (_target._color_write != _state._color_write) { if (CLP(color_mask)) { - unsigned int channels = _target._color_write->get_channels(); + unsigned int channels = _target._color_write->get_channels(); GLP(ColorMask)((channels & ColorWriteAttrib::C_red) != 0, (channels & ColorWriteAttrib::C_green) != 0, (channels & ColorWriteAttrib::C_blue) != 0, @@ -3576,7 +3559,7 @@ is_at_least_version(int major_version, int minor_version, return false; } else if (_gl_version_minor == minor_version) { if (_gl_version_release < release_version) { - return false; + return false; } } } @@ -4592,9 +4575,6 @@ set_state_and_transform(const RenderState *target, // attributes we issue. Impose them now. _target._texture = _target._texture->filter_to_max(_max_texture_stages); - bool needs_tex_gen = false; - bool needs_tex_mat = false; - if (_target._alpha_test != _state._alpha_test) { do_issue_alpha_test(); _state._alpha_test = _target._alpha_test; @@ -4660,22 +4640,6 @@ set_state_and_transform(const RenderState *target, _state._shade_model = _target._shade_model; } - if (_target._shader != _state._shader) { - do_issue_shader(); - _state._shader = _target._shader; - } - - if (_target._tex_gen != _state._tex_gen) { - _state._tex_gen = _target._tex_gen; - needs_tex_gen = true; - _state._tex_gen = _target._tex_gen; - } - - if (_target._tex_matrix != _state._tex_matrix) { - needs_tex_mat = true; - _state._tex_matrix = _target._tex_matrix; - } - if ((_target._transparency != _state._transparency)|| (_target._color_write != _state._color_write)|| (_target._color_blend != _state._color_blend)) { @@ -4685,16 +4649,19 @@ set_state_and_transform(const RenderState *target, _state._color_blend = _target._color_blend; } + if (_target._shader != _state._shader) { + do_issue_shader(); + _state._shader = _target._shader; + _state._texture = 0; + } + if (_target._texture != _state._texture) { do_issue_texture(); _state._texture = _target._texture; - - // Changing the set of texture stages will require us to reissue the - // texgen and texmat attribs. - needs_tex_gen = true; - needs_tex_mat = true; + _state._tex_gen = 0; + _state._tex_matrix = 0; } - + if (_target._material != _state._material) { do_issue_material(); _state._material = _target._material; @@ -4708,278 +4675,24 @@ set_state_and_transform(const RenderState *target, // If one of the previously-loaded TexGen modes modified the texture // matrix, then if either state changed, we have to change both of // them now. - if (_tex_gen_modifies_mat && (needs_tex_mat || needs_tex_gen)) { - needs_tex_mat = true; - needs_tex_gen = true; + if (_tex_gen_modifies_mat) { + if ((_target._tex_gen != _state._tex_gen) || + (_target._tex_matrix != _state._tex_matrix)) { + _state._tex_matrix = 0; + _state._tex_gen = 0; + } } - - // Apply the texture matrix, if needed. - if (needs_tex_mat) { - int num_stages = _state._texture->get_num_on_stages(); - nassertv(num_stages <= _max_texture_stages); - - for (int i = 0; i < num_stages; i++) { - TextureStage *stage = _state._texture->get_on_stage(i); - _glActiveTexture(GL_TEXTURE0 + i); - - GLP(MatrixMode)(GL_TEXTURE); - if (_state._tex_matrix->has_stage(stage)) { - GLP(LoadMatrixf)(_state._tex_matrix->get_mat(stage).get_data()); - } else { - GLP(LoadIdentity)(); - - // For some reason, the glLoadIdentity() call doesn't work on - // my Dell laptop's IBM OpenGL driver, when used in - // conjunction with glTexGen(), below. But explicitly loading - // an identity matrix does work. But this buggy-driver - // workaround might have other performance implications, so I - // leave it out. - //GLP(LoadMatrixf)(LMatrix4f::ident_mat().get_data()); - } - } - report_my_gl_errors(); + + if (_target._tex_matrix != _state._tex_matrix) { + do_issue_tex_matrix(); + _state._tex_matrix = _target._tex_matrix; } - - if (needs_tex_gen) { - bool force_normal = false; - - int num_stages = _state._texture->get_num_on_stages(); - nassertv(num_stages <= _max_texture_stages); - - // These are passed in for the four OBJECT_PLANE or EYE_PLANE - // values; they effectively define an identity matrix that maps - // the spatial coordinates one-for-one to UV's. If you want a - // mapping other than identity, use a TexMatrixAttrib (or a - // TexProjectorEffect). - static const float s_data[4] = { 1, 0, 0, 0 }; - static const float t_data[4] = { 0, 1, 0, 0 }; - static const float r_data[4] = { 0, 0, 1, 0 }; - static const float q_data[4] = { 0, 0, 0, 1 }; - - _tex_gen_modifies_mat = false; - - bool got_point_sprites = false; - - for (int i = 0; i < num_stages; i++) { - TextureStage *stage = _state._texture->get_on_stage(i); - _glActiveTexture(GL_TEXTURE0 + i); - GLP(Disable)(GL_TEXTURE_GEN_S); - GLP(Disable)(GL_TEXTURE_GEN_T); - GLP(Disable)(GL_TEXTURE_GEN_R); - GLP(Disable)(GL_TEXTURE_GEN_Q); - if (_supports_point_sprite) { - GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE); - } - - TexGenAttrib::Mode mode = _state._tex_gen->get_mode(stage); - switch (mode) { - case TexGenAttrib::M_off: - case TexGenAttrib::M_light_vector: - break; - - case TexGenAttrib::M_eye_sphere_map: - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - force_normal = true; - break; - - case TexGenAttrib::M_eye_cube_map: - if (_supports_cube_map) { - // We need to rotate the normals out of GL's coordinate - // system and into the user's coordinate system. We do this - // by composing a transform onto the texture matrix. - LMatrix4f mat = _inv_cs_transform->get_mat(); - mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f)); - GLP(MatrixMode)(GL_TEXTURE); - GLP(MultMatrixf)(mat.get_data()); - - // Now we need to reset the texture matrix next time - // around to undo this. - _tex_gen_modifies_mat = true; - - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - force_normal = true; - } - break; - - case TexGenAttrib::M_world_cube_map: - if (_supports_cube_map) { - // We dynamically transform normals from eye space to world - // space by applying the appropriate rotation transform to - // the current texture matrix. Unlike M_world_position, we - // can't achieve this effect by monkeying with the modelview - // transform, since the current modelview doesn't affect - // GL_REFLECTION_MAP. - CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); - - LMatrix4f mat = camera_transform->get_mat(); - mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f)); - GLP(MatrixMode)(GL_TEXTURE); - GLP(MultMatrixf)(mat.get_data()); - - // Now we need to reset the texture matrix next time - // around to undo this. - _tex_gen_modifies_mat = true; - - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - force_normal = true; - } - break; - - case TexGenAttrib::M_eye_normal: - if (_supports_cube_map) { - // We need to rotate the normals out of GL's coordinate - // system and into the user's coordinate system. We do this - // by composing a transform onto the texture matrix. - LMatrix4f mat = _inv_cs_transform->get_mat(); - mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f)); - GLP(MatrixMode)(GL_TEXTURE); - GLP(MultMatrixf)(mat.get_data()); - - // Now we need to reset the texture matrix next time - // around to undo this. - _tex_gen_modifies_mat = true; - - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - force_normal = true; - } - break; - - case TexGenAttrib::M_world_normal: - if (_supports_cube_map) { - // We dynamically transform normals from eye space to world - // space by applying the appropriate rotation transform to - // the current texture matrix. Unlike M_world_position, we - // can't achieve this effect by monkeying with the modelview - // transform, since the current modelview doesn't affect - // GL_NORMAL_MAP. - CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); - - LMatrix4f mat = camera_transform->get_mat(); - mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f)); - GLP(MatrixMode)(GL_TEXTURE); - GLP(MultMatrixf)(mat.get_data()); - - // Now we need to reset the texture matrix next time - // around to undo this. - _tex_gen_modifies_mat = true; - - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - force_normal = true; - } - break; - - case TexGenAttrib::M_eye_position: - // To represent eye position correctly, we need to temporarily - // load the coordinate-system transform. - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PushMatrix)(); - GLP(LoadMatrixf)(_cs_transform->get_mat().get_data()); - - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - - GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data); - GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data); - GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data); - GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data); - - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - GLP(Enable)(GL_TEXTURE_GEN_Q); - - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PopMatrix)(); - break; - - case TexGenAttrib::M_world_position: - // We achieve world position coordinates by using the eye - // position mode, and loading the transform of the root - // node--thus putting the "eye" at the root. - { - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PushMatrix)(); - CPT(TransformState) root_transform = _cs_transform->compose(_scene_setup->get_world_transform()); - GLP(LoadMatrixf)(root_transform->get_mat().get_data()); - GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); - - GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data); - GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data); - GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data); - GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data); - - GLP(Enable)(GL_TEXTURE_GEN_S); - GLP(Enable)(GL_TEXTURE_GEN_T); - GLP(Enable)(GL_TEXTURE_GEN_R); - GLP(Enable)(GL_TEXTURE_GEN_Q); - - GLP(MatrixMode)(GL_MODELVIEW); - GLP(PopMatrix)(); - } - break; - - case TexGenAttrib::M_point_sprite: - nassertv(_supports_point_sprite); - GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); - got_point_sprites = true; - break; - - case TexGenAttrib::M_unused: - break; - } - } - - if (got_point_sprites != _tex_gen_point_sprite) { - _tex_gen_point_sprite = got_point_sprites; - if (_tex_gen_point_sprite) { - GLP(Enable)(GL_POINT_SPRITE_ARB); - } else { - GLP(Disable)(GL_POINT_SPRITE_ARB); - } - } - - // Certain texgen modes (sphere_map, cube_map) require forcing the - // normal to be sent to the GL while the texgen mode is in effect. - if (force_normal != _texgen_forced_normal) { - if (force_normal) { - force_normals(); - } else { - undo_force_normals(); - } - _texgen_forced_normal = force_normal; - } - - report_my_gl_errors(); + + if (_target._tex_gen != _state._tex_gen) { + do_issue_tex_gen(); + _state._tex_gen = _target._tex_gen; } - + _state_rs = _target_rs; } @@ -5030,19 +4743,47 @@ do_auto_rescale_normal() { //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::do_issue_texture // Access: Protected, Virtual -// Description: This is called by finish_modify_state() when the -// texture state has changed. +// Description: This is called by set_state_and_transform() when +// the texture state has changed. //////////////////////////////////////////////////////////////////// void CLP(GraphicsStateGuardian):: do_issue_texture() { DO_PSTATS_STUFF(_texture_state_pcollector.add_level(1)); + + if (_texture_binding_shader_context==0) { + if (_current_shader_context==0) { + update_standard_texture_bindings(); + } else { + disable_standard_texture_bindings(); + _current_shader_context->update_shader_texture_bindings(NULL,this); + } + } else { + if (_current_shader_context==0) { + _texture_binding_shader_context->disable_shader_texture_bindings(this); + update_standard_texture_bindings(); + } else { + _current_shader_context-> + update_shader_texture_bindings(_texture_binding_shader_context,this); + } + } + _texture_binding_shader_expansion = _current_shader_expansion; + _texture_binding_shader_context = _current_shader_context; +} +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::update_standard_texture_bindings +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +update_standard_texture_bindings() +{ int num_stages = _target._texture->get_num_on_stages(); int num_old_stages = _max_texture_stages; if (_state._texture != (TextureAttrib *)NULL) { num_old_stages = _state._texture->get_num_on_stages(); } - + nassertv(num_stages <= _max_texture_stages && num_old_stages <= _max_texture_stages); @@ -5057,7 +4798,7 @@ do_issue_texture() { nassertv(texture != (Texture *)NULL); if (i >= num_old_stages || - _state._texture == (TextureAttrib *)NULL || + _state._texture == (TextureAttrib *)NULL || stage != _state._texture->get_on_stage(i) || texture != _state._texture->get_on_texture(stage) || stage->involves_color_scale()) { @@ -5202,7 +4943,7 @@ do_issue_texture() { } GLP(MatrixMode)(GL_TEXTURE); - if (_state._tex_matrix->has_stage(stage)) { + if (_target._tex_matrix->has_stage(stage)) { GLP(LoadMatrixf)(_state._tex_matrix->get_mat(stage).get_data()); } else { GLP(LoadIdentity)(); @@ -5236,6 +4977,313 @@ do_issue_texture() { report_my_gl_errors(); } + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::disable_standard_texture_bindings +// Access: Private +// Description: +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +disable_standard_texture_bindings() { + int num_old_stages = _max_texture_stages; + if (_state._texture != (TextureAttrib *)NULL) { + num_old_stages = _state._texture->get_num_on_stages(); + } + + // Disable the texture stages that are no longer used. + for (int i = 0; i < num_old_stages; i++) { + _glActiveTexture(GL_TEXTURE0 + i); + GLP(Disable)(GL_TEXTURE_1D); + GLP(Disable)(GL_TEXTURE_2D); + if (_supports_3d_texture) { + GLP(Disable)(GL_TEXTURE_3D); + } + if (_supports_cube_map) { + GLP(Disable)(GL_TEXTURE_CUBE_MAP); + } + } + + report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::do_issue_tex_matrix +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +do_issue_tex_matrix() { + int num_stages = _target._texture->get_num_on_stages(); + nassertv(num_stages <= _max_texture_stages); + + for (int i = 0; i < num_stages; i++) { + TextureStage *stage = _target._texture->get_on_stage(i); + _glActiveTexture(GL_TEXTURE0 + i); + + GLP(MatrixMode)(GL_TEXTURE); + if (_target._tex_matrix->has_stage(stage)) { + GLP(LoadMatrixf)(_target._tex_matrix->get_mat(stage).get_data()); + } else { + GLP(LoadIdentity)(); + + // For some reason, the glLoadIdentity() call doesn't work on + // my Dell laptop's IBM OpenGL driver, when used in + // conjunction with glTexGen(), below. But explicitly loading + // an identity matrix does work. But this buggy-driver + // workaround might have other performance implications, so I + // leave it out. + //GLP(LoadMatrixf)(LMatrix4f::ident_mat().get_data()); + } + } + report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::do_issue_tex_gen +// Access: Protected +// Description: +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +do_issue_tex_gen() { + bool force_normal = false; + + int num_stages = _target._texture->get_num_on_stages(); + nassertv(num_stages <= _max_texture_stages); + + // These are passed in for the four OBJECT_PLANE or EYE_PLANE + // values; they effectively define an identity matrix that maps + // the spatial coordinates one-for-one to UV's. If you want a + // mapping other than identity, use a TexMatrixAttrib (or a + // TexProjectorEffect). + static const float s_data[4] = { 1, 0, 0, 0 }; + static const float t_data[4] = { 0, 1, 0, 0 }; + static const float r_data[4] = { 0, 0, 1, 0 }; + static const float q_data[4] = { 0, 0, 0, 1 }; + + _tex_gen_modifies_mat = false; + + bool got_point_sprites = false; + + for (int i = 0; i < num_stages; i++) { + TextureStage *stage = _target._texture->get_on_stage(i); + _glActiveTexture(GL_TEXTURE0 + i); + GLP(Disable)(GL_TEXTURE_GEN_S); + GLP(Disable)(GL_TEXTURE_GEN_T); + GLP(Disable)(GL_TEXTURE_GEN_R); + GLP(Disable)(GL_TEXTURE_GEN_Q); + if (_supports_point_sprite) { + GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_FALSE); + } + + TexGenAttrib::Mode mode = _target._tex_gen->get_mode(stage); + switch (mode) { + case TexGenAttrib::M_off: + case TexGenAttrib::M_light_vector: + break; + + case TexGenAttrib::M_eye_sphere_map: + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + force_normal = true; + break; + + case TexGenAttrib::M_eye_cube_map: + if (_supports_cube_map) { + // We need to rotate the normals out of GL's coordinate + // system and into the user's coordinate system. We do this + // by composing a transform onto the texture matrix. + LMatrix4f mat = _inv_cs_transform->get_mat(); + mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f)); + GLP(MatrixMode)(GL_TEXTURE); + GLP(MultMatrixf)(mat.get_data()); + + // Now we need to reset the texture matrix next time + // around to undo this. + _tex_gen_modifies_mat = true; + + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + force_normal = true; + } + break; + + case TexGenAttrib::M_world_cube_map: + if (_supports_cube_map) { + // We dynamically transform normals from eye space to world + // space by applying the appropriate rotation transform to + // the current texture matrix. Unlike M_world_position, we + // can't achieve this effect by monkeying with the modelview + // transform, since the current modelview doesn't affect + // GL_REFLECTION_MAP. + CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); + + LMatrix4f mat = camera_transform->get_mat(); + mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f)); + GLP(MatrixMode)(GL_TEXTURE); + GLP(MultMatrixf)(mat.get_data()); + + // Now we need to reset the texture matrix next time + // around to undo this. + _tex_gen_modifies_mat = true; + + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP); + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + force_normal = true; + } + break; + + case TexGenAttrib::M_eye_normal: + if (_supports_cube_map) { + // We need to rotate the normals out of GL's coordinate + // system and into the user's coordinate system. We do this + // by composing a transform onto the texture matrix. + LMatrix4f mat = _inv_cs_transform->get_mat(); + mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f)); + GLP(MatrixMode)(GL_TEXTURE); + GLP(MultMatrixf)(mat.get_data()); + + // Now we need to reset the texture matrix next time + // around to undo this. + _tex_gen_modifies_mat = true; + + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + force_normal = true; + } + break; + + case TexGenAttrib::M_world_normal: + if (_supports_cube_map) { + // We dynamically transform normals from eye space to world + // space by applying the appropriate rotation transform to + // the current texture matrix. Unlike M_world_position, we + // can't achieve this effect by monkeying with the modelview + // transform, since the current modelview doesn't affect + // GL_NORMAL_MAP. + CPT(TransformState) camera_transform = _scene_setup->get_camera_transform()->compose(_inv_cs_transform); + + LMatrix4f mat = camera_transform->get_mat(); + mat.set_row(3, LVecBase3f(0.0f, 0.0f, 0.0f)); + GLP(MatrixMode)(GL_TEXTURE); + GLP(MultMatrixf)(mat.get_data()); + + // Now we need to reset the texture matrix next time + // around to undo this. + _tex_gen_modifies_mat = true; + + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP); + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + force_normal = true; + } + break; + + case TexGenAttrib::M_eye_position: + // To represent eye position correctly, we need to temporarily + // load the coordinate-system transform. + GLP(MatrixMode)(GL_MODELVIEW); + GLP(PushMatrix)(); + GLP(LoadMatrixf)(_cs_transform->get_mat().get_data()); + + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + + GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data); + GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data); + GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data); + GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data); + + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + GLP(Enable)(GL_TEXTURE_GEN_Q); + + GLP(MatrixMode)(GL_MODELVIEW); + GLP(PopMatrix)(); + break; + + case TexGenAttrib::M_world_position: + // We achieve world position coordinates by using the eye + // position mode, and loading the transform of the root + // node--thus putting the "eye" at the root. + { + GLP(MatrixMode)(GL_MODELVIEW); + GLP(PushMatrix)(); + CPT(TransformState) root_transform = _cs_transform->compose(_scene_setup->get_world_transform()); + GLP(LoadMatrixf)(root_transform->get_mat().get_data()); + GLP(TexGeni)(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + GLP(TexGeni)(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); + + GLP(TexGenfv)(GL_S, GL_EYE_PLANE, s_data); + GLP(TexGenfv)(GL_T, GL_EYE_PLANE, t_data); + GLP(TexGenfv)(GL_R, GL_EYE_PLANE, r_data); + GLP(TexGenfv)(GL_Q, GL_EYE_PLANE, q_data); + + GLP(Enable)(GL_TEXTURE_GEN_S); + GLP(Enable)(GL_TEXTURE_GEN_T); + GLP(Enable)(GL_TEXTURE_GEN_R); + GLP(Enable)(GL_TEXTURE_GEN_Q); + + GLP(MatrixMode)(GL_MODELVIEW); + GLP(PopMatrix)(); + } + break; + + case TexGenAttrib::M_point_sprite: + nassertv(_supports_point_sprite); + GLP(TexEnvi)(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, GL_TRUE); + got_point_sprites = true; + break; + + case TexGenAttrib::M_unused: + break; + } + } + + if (got_point_sprites != _tex_gen_point_sprite) { + _tex_gen_point_sprite = got_point_sprites; + if (_tex_gen_point_sprite) { + GLP(Enable)(GL_POINT_SPRITE_ARB); + } else { + GLP(Disable)(GL_POINT_SPRITE_ARB); + } + } + + // Certain texgen modes (sphere_map, cube_map) require forcing the + // normal to be sent to the GL while the texgen mode is in effect. + if (force_normal != _texgen_forced_normal) { + if (force_normal) { + force_normals(); + } else { + undo_force_normals(); + } + _texgen_forced_normal = force_normal; + } + + report_my_gl_errors(); +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::specify_texture // Access: Protected diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index e9b9f58f6f..f8b34038ea 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -177,6 +177,8 @@ protected: void do_issue_material(); void do_issue_texture(); void do_issue_blending(); + void do_issue_tex_gen(); + void do_issue_tex_matrix(); static bool report_errors_loop(int line, const char *source_file, GLenum error_code, int &error_count); @@ -249,6 +251,8 @@ protected: void disable_standard_vertex_arrays(); void update_standard_vertex_arrays(); + void disable_standard_texture_bindings(); + void update_standard_texture_bindings(); void do_auto_rescale_normal(); void specify_texture(Texture *tex); @@ -310,6 +314,8 @@ protected: CLP(ShaderContext) *_current_shader_context; PT(ShaderExpansion) _vertex_array_shader_expansion; CLP(ShaderContext) *_vertex_array_shader_context; + PT(ShaderExpansion) _texture_binding_shader_expansion; + CLP(ShaderContext) *_texture_binding_shader_context; CPT(DisplayRegion) _actual_display_region; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index 33062d63a2..7b985281de 100755 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -307,6 +307,84 @@ update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg) #endif // HAVE_CGGL } +//////////////////////////////////////////////////////////////////// +// Function: GLShaderContext::disable_shader_texture_bindings +// Access: Public +// Description: Disable all the texture bindings used by this shader. +//////////////////////////////////////////////////////////////////// +void CLP(ShaderContext):: +disable_shader_texture_bindings(GSG *gsg) +{ +#ifdef HAVE_CGGL + if (_cg_context) { + for (int i=0; i<(int)_cg_texbind.size(); i++) { + int texunit = cgGetParameterResourceIndex(_cg_texbind[i].parameter); + gsg->_glActiveTexture(GL_TEXTURE0 + texunit); + GLP(Disable)(GL_TEXTURE_1D); + GLP(Disable)(GL_TEXTURE_2D); + if (gsg->_supports_3d_texture) { + GLP(Disable)(GL_TEXTURE_3D); + } + if (gsg->_supports_cube_map) { + GLP(Disable)(GL_TEXTURE_CUBE_MAP); + } + // This is probably faster - but maybe not as safe? + // cgGLDisableTextureParameter(_cg_texbind[i].parameter); + } + } +#endif +} + +//////////////////////////////////////////////////////////////////// +// Function: GLShaderContext::update_shader_texture_bindings +// Access: Public +// Description: Disables all texture bindings used by the previous +// shader, then enables all the texture bindings needed +// by this shader. Extracts the relevant vertex array +// data from the gsg. +// The current implementation is inefficient, because +// it may unnecessarily disable textures then immediately +// reenable them. We may optimize this someday. +//////////////////////////////////////////////////////////////////// +void CLP(ShaderContext):: +update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg) +{ + if (prev) prev->disable_shader_texture_bindings(gsg); +#ifdef HAVE_CGGL + if (_cg_context) { + for (int i=0; i<(int)_cg_texbind.size(); i++) { + Texture *tex = 0; + InternalName *id = _cg_texbind[i].name; + if (id != 0) { + const ShaderInput *input = gsg->_target._shader->get_input(id); + tex = input->get_texture(); + } else { + TextureStage *stage = gsg->_target._texture->get_on_stage(_cg_texbind[i].stage); + tex = gsg->_target._texture->get_on_texture(stage); + } + if ((tex == 0) || (tex->get_texture_type() != _cg_texbind[i].desiredtype)) { + continue; + } + TextureContext *tc = tex->prepare_now(gsg->_prepared_objects, gsg); + if (tc == (TextureContext*)NULL) { + continue; + } + int texunit = cgGetParameterResourceIndex(_cg_texbind[i].parameter); + gsg->_glActiveTexture(GL_TEXTURE0 + texunit); + + GLenum target = gsg->get_texture_target(tex->get_texture_type()); + if (target == GL_NONE) { + // Unsupported texture mode. + continue; + } + GLP(Enable)(target); + + gsg->apply_texture(tc); + } + } +#endif +} + #ifdef HAVE_CGGL //////////////////////////////////////////////////////////////////// // Function: GLShaderContext::bind_cg_transform @@ -321,6 +399,8 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg) if (stb.src_name == InternalName::get_camera()) { src = TransformState::make_identity(); + } else if (stb.src_name == InternalName::get_view()) { + src = gsg->_cs_transform; } else if (stb.src_name == InternalName::get_model()) { src = gsg->get_transform(); } else if (stb.src_name == InternalName::get_world()) { @@ -337,6 +417,8 @@ bind_cg_transform(const ShaderTransBind &stb, GSG *gsg) if (stb.rel_name == InternalName::get_camera()) { rel = TransformState::make_identity(); + } else if (stb.src_name == InternalName::get_view()) { + rel = gsg->_cs_transform; } else if (stb.rel_name == InternalName::get_model()) { rel = gsg->get_transform(); } else if (stb.rel_name == InternalName::get_world()) { @@ -498,7 +580,10 @@ bool CLP(ShaderContext):: errchk_cg_parameter_sampler(CGparameter p) { CGtype t = cgGetParameterType(p); - if (t != CG_SAMPLER2D) { + if ((t!=CG_SAMPLER1D)&& + (t!=CG_SAMPLER2D)&& + (t!=CG_SAMPLER3D)&& + (t!=CG_SAMPLERCUBE)) { errchk_cg_output(p, "parameter should have a 'sampler' type"); return false; } @@ -744,8 +829,21 @@ compile_cg_parameter(CGparameter p) (!errchk_cg_parameter_variance(p, CG_UNIFORM)) || (!errchk_cg_parameter_sampler(p))) return false; - // IMPLEMENT ME - return true; // Cg handles this automatically. + ShaderTexBind bind; + bind.parameter = p; + bind.name = 0; + bind.stage = atoi(pieces[1].c_str()); + switch (cgGetParameterType(p)) { + case CG_SAMPLER1D: bind.desiredtype = Texture::TT_1d_texture; break; + case CG_SAMPLER2D: bind.desiredtype = Texture::TT_2d_texture; break; + case CG_SAMPLER3D: bind.desiredtype = Texture::TT_3d_texture; break; + case CG_SAMPLERCUBE: bind.desiredtype = Texture::TT_cube_map; break; + default: + errchk_cg_output(p, "Invalid type for a tex-parameter"); + return false; + } + _cg_texbind.push_back(bind); + return true; } if (pieces[0] == "k") { @@ -753,14 +851,53 @@ compile_cg_parameter(CGparameter p) (!errchk_cg_parameter_direction(p, CG_IN)) || (!errchk_cg_parameter_variance(p, CG_UNIFORM))) return false; - ShaderArgBind bind; - bind.parameter = p; - bind.name = InternalName::make(pieces[1]); switch (cgGetParameterType(p)) { - case CG_FLOAT4: _cg_fbind.push_back(bind); break; - case CG_SAMPLER2D: _cg_tbind2d.push_back(bind); break; - case CG_SAMPLER3D: _cg_tbind3d.push_back(bind); break; - case CG_FLOAT4x4: _cg_npbind.push_back(bind); break; + case CG_FLOAT4: { + ShaderArgBind bind; + bind.parameter = p; + bind.name = InternalName::make(pieces[1]); + _cg_fbind.push_back(bind); + break; + } + case CG_FLOAT4x4: { + ShaderArgBind bind; + bind.parameter = p; + bind.name = InternalName::make(pieces[1]); + _cg_npbind.push_back(bind); + break; + } + case CG_SAMPLER1D: { + ShaderTexBind bind; + bind.parameter = p; + bind.name = InternalName::make(pieces[1]); + bind.desiredtype=Texture::TT_1d_texture; + _cg_texbind.push_back(bind); + break; + } + case CG_SAMPLER2D: { + ShaderTexBind bind; + bind.parameter = p; + bind.name = InternalName::make(pieces[1]); + bind.desiredtype=Texture::TT_2d_texture; + _cg_texbind.push_back(bind); + break; + } + case CG_SAMPLER3D: { + ShaderTexBind bind; + bind.parameter = p; + bind.name = InternalName::make(pieces[1]); + bind.desiredtype=Texture::TT_3d_texture; + _cg_texbind.push_back(bind); + break; + } + case CG_SAMPLERCUBE: { + ShaderTexBind bind; + bind.parameter = p; + bind.name = InternalName::make(pieces[1]); + bind.desiredtype = Texture::TT_cube_map; + _cg_texbind.push_back(bind); + break; + } default: errchk_cg_output(p, "Invalid type for a k-parameter"); return false; diff --git a/panda/src/glstuff/glShaderContext_src.h b/panda/src/glstuff/glShaderContext_src.h index c96e70a675..4c88cdba08 100755 --- a/panda/src/glstuff/glShaderContext_src.h +++ b/panda/src/glstuff/glShaderContext_src.h @@ -45,6 +45,8 @@ public: void issue_transform(GSG *gsg); void disable_shader_vertex_arrays(GSG *gsg); void update_shader_vertex_arrays(CLP(ShaderContext) *prev, GSG *gsg); + void disable_shader_texture_bindings(GSG *gsg); + void update_shader_texture_bindings(CLP(ShaderContext) *prev, GSG *gsg); private: @@ -58,6 +60,12 @@ private: CGparameter parameter; PT(InternalName) name; }; + struct ShaderTexBind { + CGparameter parameter; + PT(InternalName) name; + int stage; + int desiredtype; + }; struct ShaderTransBind { CGparameter parameter; PT(InternalName) src_name; @@ -76,10 +84,9 @@ private: // These arrays contain lists of "bindings." They // tell us how to fill the shader's input parameters. vector _cg_autobind; - vector _cg_tbind2d; - vector _cg_tbind3d; vector _cg_fbind; vector _cg_npbind; + vector _cg_texbind; vector _cg_transform_bind; vector _cg_parameter_bind; vector _cg_varying; diff --git a/panda/src/gobj/internalName.I b/panda/src/gobj/internalName.I index 76b1e7e3d6..d37991adb2 100644 --- a/panda/src/gobj/internalName.I +++ b/panda/src/gobj/internalName.I @@ -417,6 +417,20 @@ get_model() { return _model; } +//////////////////////////////////////////////////////////////////// +// Function: InternalName::get_view +// Access: Published, Static +// Description: Returns the standard InternalName "view". This is +// used as a keyword in the shader subsystem. +//////////////////////////////////////////////////////////////////// +INLINE PT(InternalName) InternalName:: +get_view() { + if (_view == (InternalName *)NULL) { + _view = InternalName::make("view"); + } + return _view; +} + //////////////////////////////////////////////////////////////////// // Function: InternalName::output operator // Access: Public diff --git a/panda/src/gobj/internalName.cxx b/panda/src/gobj/internalName.cxx index 6d7cab6346..31e8c8f28c 100644 --- a/panda/src/gobj/internalName.cxx +++ b/panda/src/gobj/internalName.cxx @@ -42,6 +42,7 @@ PT(InternalName) InternalName::_index; PT(InternalName) InternalName::_world; PT(InternalName) InternalName::_camera; PT(InternalName) InternalName::_model; +PT(InternalName) InternalName::_view; TypeHandle InternalName::_type_handle; TypeHandle InternalName::_texcoord_type_handle; diff --git a/panda/src/gobj/internalName.h b/panda/src/gobj/internalName.h index 2d62289319..c60f4ac145 100644 --- a/panda/src/gobj/internalName.h +++ b/panda/src/gobj/internalName.h @@ -84,6 +84,7 @@ PUBLISHED: INLINE static PT(InternalName) get_world(); INLINE static PT(InternalName) get_camera(); INLINE static PT(InternalName) get_model(); + INLINE static PT(InternalName) get_view(); private: PT(InternalName) _parent; @@ -111,6 +112,7 @@ private: static PT(InternalName) _world; static PT(InternalName) _camera; static PT(InternalName) _model; + static PT(InternalName) _view; public: // Datagram stuff