From 7d8cbc7a10b3488f94da02d67863e402bdeb877d Mon Sep 17 00:00:00 2001 From: David Rose Date: Mon, 2 May 2005 00:29:24 +0000 Subject: [PATCH] straighten out some confusing texture interfaces --- panda/src/display/graphicsStateGuardian.cxx | 39 +- panda/src/display/graphicsStateGuardian.h | 1 - panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx | 35 +- panda/src/dxgsg7/dxGraphicsStateGuardian7.h | 8 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 36 +- panda/src/dxgsg8/dxGraphicsStateGuardian8.h | 8 +- panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx | 33 +- panda/src/dxgsg9/dxGraphicsStateGuardian9.h | 8 +- .../glstuff/glGraphicsStateGuardian_src.cxx | 1074 ++++++++--------- .../src/glstuff/glGraphicsStateGuardian_src.h | 21 +- panda/src/glstuff/glTextureContext_src.I | 1 - panda/src/glstuff/glTextureContext_src.h | 3 - panda/src/gobj/texture.I | 12 +- panda/src/gobj/texture.cxx | 25 +- panda/src/gobj/texture.h | 2 +- panda/src/gobj/textureContext.I | 2 +- panda/src/gsgbase/graphicsStateGuardianBase.h | 3 - panda/src/pgraph/Sources.pp | 3 - panda/src/pgraph/config_pgraph.cxx | 3 - panda/src/pgraph/lensNode.I | 18 +- panda/src/pgraph/lensNode.cxx | 44 +- panda/src/pgraph/lensNode.h | 4 + panda/src/pgraph/pgraph_composite4.cxx | 1 - panda/src/pgraph/spotlight.cxx | 122 +- panda/src/pgraph/spotlight.h | 5 +- panda/src/pgraph/textureApplyAttrib.I | 40 - panda/src/pgraph/textureApplyAttrib.cxx | 179 --- panda/src/pgraph/textureApplyAttrib.h | 95 -- panda/src/pnmimage/pnmImage.I | 163 ++- panda/src/pnmimage/pnmImage.cxx | 105 +- panda/src/pnmimage/pnmImage.h | 7 + panda/src/pnmimage/pnmImageHeader.I | 32 +- panda/src/pnmimage/pnmImageHeader.cxx | 14 +- .../wgldisplay/wglGraphicsStateGuardian.cxx | 8 +- 34 files changed, 953 insertions(+), 1201 deletions(-) delete mode 100644 panda/src/pgraph/textureApplyAttrib.I delete mode 100644 panda/src/pgraph/textureApplyAttrib.cxx delete mode 100644 panda/src/pgraph/textureApplyAttrib.h diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index 0d265a9822..5bf365d8ad 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -252,34 +252,27 @@ get_prepared_objects() { //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::prepare_texture // Access: Public, Virtual -// Description: Prepares the indicated texture for retained-mode -// rendering. In the future, this texture may be -// applied simply by calling apply_texture() with the -// value returned by this function. +// Description: Creates whatever structures the GSG requires to +// represent the texture internally, and returns a +// newly-allocated TextureContext object with this data. +// It is the responsibility of the calling function to +// later call release_texture() with this same pointer +// (which will also delete the pointer). +// +// This function should not be called directly to +// prepare a texture. Instead, call Texture::prepare(). //////////////////////////////////////////////////////////////////// TextureContext *GraphicsStateGuardian:: prepare_texture(Texture *) { return (TextureContext *)NULL; } -//////////////////////////////////////////////////////////////////// -// Function: GraphicsStateGuardian::apply_texture -// Access: Public, Virtual -// Description: Applies the texture previously indicated via a call -// to prepare_texture() to the graphics state, so that -// geometry rendered in the future will be rendered with -// the given texture. -//////////////////////////////////////////////////////////////////// -void GraphicsStateGuardian:: -apply_texture(TextureContext *, int index) { -} - //////////////////////////////////////////////////////////////////// // Function: GraphicsStateGuardian::release_texture // Access: Public, Virtual // Description: Frees the resources previously allocated via a call // to prepare_texture(), including deleting the -// TextureContext itself, if necessary. +// TextureContext itself, if it is non-NULL. //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: release_texture(TextureContext *) { @@ -289,9 +282,10 @@ release_texture(TextureContext *) { // Function: GraphicsStateGuardian::prepare_geom // Access: Public, Virtual // Description: Prepares the indicated Geom for retained-mode -// rendering. The value returned by this function will -// be passed back into future calls to draw_tristrip(), -// etc., along with the Geom pointer. +// rendering, by creating whatever structures are +// necessary in the GSG (for instance, vertex buffers). +// Returns the newly-allocated GeomContext that can be +// used to render the geom. //////////////////////////////////////////////////////////////////// GeomContext *GraphicsStateGuardian:: prepare_geom(Geom *) { @@ -303,7 +297,10 @@ prepare_geom(Geom *) { // Access: Public, Virtual // Description: Frees the resources previously allocated via a call // to prepare_geom(), including deleting the GeomContext -// itself, if necessary. +// itself, if it is non-NULL. +// +// This function should not be called directly to +// prepare a Geom. Instead, call Geom::prepare(). //////////////////////////////////////////////////////////////////// void GraphicsStateGuardian:: release_geom(GeomContext *) { diff --git a/panda/src/display/graphicsStateGuardian.h b/panda/src/display/graphicsStateGuardian.h index d00accd254..553f1ba0b6 100644 --- a/panda/src/display/graphicsStateGuardian.h +++ b/panda/src/display/graphicsStateGuardian.h @@ -107,7 +107,6 @@ public: virtual PreparedGraphicsObjects *get_prepared_objects(); virtual TextureContext *prepare_texture(Texture *tex); - virtual void apply_texture(TextureContext *tc, int index=0); virtual void release_texture(TextureContext *tc); virtual GeomContext *prepare_geom(Geom *geom); diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx index a190da6865..300bb5f233 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.cxx @@ -598,7 +598,7 @@ dx_init( void) { // must do SetTSS here because redundant states are filtered out by our code based on current values above, so // initial conditions must be correct - _CurTexBlendMode = TextureApplyAttrib::M_modulate; + _CurTexBlendMode = TextureStage::M_modulate; SetTextureBlendMode(_CurTexBlendMode,FALSE); _texturing_enabled = false; _pScrn->pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); // disables texturing @@ -1749,9 +1749,7 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { Texture *tex = geom->get_texture(); if(tex !=NULL) { // set up the texture-rendering state - modify_state(RenderState::make - (TextureAttrib::make(tex), - TextureApplyAttrib::make(TextureApplyAttrib::M_modulate))); + modify_state(RenderState::make(TextureAttrib::make(tex))); tex_xsize = tex->get_x_size(); tex_ysize = tex->get_y_size(); } @@ -3315,7 +3313,7 @@ prepare_texture(Texture *tex) { //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian7::apply_texture -// Access: Public, Virtual +// Access: Public // Description: Makes the texture the currently available texture for // rendering. //////////////////////////////////////////////////////////////////// @@ -3583,13 +3581,9 @@ apply_fog(Fog *fog) { } } -void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureApplyAttrib::Mode TexBlendMode,bool bCanJustEnable) { +void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureStage::Mode TexBlendMode,bool bCanJustEnable) { -/*class TextureApplyAttrib { - enum Mode { - M_modulate,M_decal,M_blend,M_replace,M_add}; -*/ - static D3DTEXTUREOP TexBlendColorOp1[/* TextureApplyAttrib::Mode maxval*/ 10] = + static D3DTEXTUREOP TexBlendColorOp1[/* TextureStage::Mode maxval*/ 10] = {D3DTOP_MODULATE,D3DTOP_BLENDTEXTUREALPHA,D3DTOP_MODULATE,D3DTOP_SELECTARG1,D3DTOP_ADD}; //if bCanJustEnable, then we only need to make sure ColorOp is turned on and set properly @@ -3603,7 +3597,7 @@ void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureApplyAttrib::Mode TexB switch (TexBlendMode) { - case TextureApplyAttrib::M_modulate: + case TextureStage::M_modulate: // emulates GL_MODULATE glTexEnv mode // want to multiply tex-color*pixel color to emulate GL modulate blend (see glTexEnv) _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); @@ -3613,7 +3607,7 @@ void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; - case TextureApplyAttrib::M_decal: + case TextureStage::M_decal: // emulates GL_DECAL glTexEnv mode _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); @@ -3622,13 +3616,13 @@ void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); break; - case TextureApplyAttrib::M_replace: + case TextureStage::M_replace: _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); break; - case TextureApplyAttrib::M_add: + case TextureStage::M_add: _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); @@ -3638,7 +3632,7 @@ void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pScrn->pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; - case TextureApplyAttrib::M_blend: + case TextureStage::M_blend: dxgsg7_cat.error() << "Impossible to emulate GL_BLEND in DX exactly " << (int) TexBlendMode << endl; /* @@ -3845,15 +3839,6 @@ issue_rescale_normal(const RescaleNormalAttrib *attrib) { } } -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian7::issue_texture_apply -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian7:: -issue_texture_apply(const TextureApplyAttrib *attrib) { -} - //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian7::issue_depth_test // Access: Public, Virtual diff --git a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h index 43fd46ac90..bf2a012e5a 100644 --- a/panda/src/dxgsg7/dxGraphicsStateGuardian7.h +++ b/panda/src/dxgsg7/dxGraphicsStateGuardian7.h @@ -32,7 +32,6 @@ #include "material.h" #include "depthTestAttrib.h" #include "renderModeAttrib.h" -#include "textureApplyAttrib.h" #include "fog.h" #include "pointerToArray.h" #include "graphicsWindow.h" @@ -88,7 +87,7 @@ public: virtual void draw_sphere(GeomSphere *geom, GeomContext *gc); virtual TextureContext *prepare_texture(Texture *tex); - virtual void apply_texture(TextureContext *tc); + void apply_texture(TextureContext *tc); virtual void release_texture(TextureContext *tc); virtual void framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, @@ -106,7 +105,6 @@ public: virtual void issue_material(const MaterialAttrib *attrib); virtual void issue_render_mode(const RenderModeAttrib *attrib); virtual void issue_rescale_normal(const RescaleNormalAttrib *attrib); - virtual void issue_texture_apply(const TextureApplyAttrib *attrib); virtual void issue_alpha_test(const AlphaTestAttrib *attrib); virtual void issue_depth_test(const DepthTestAttrib *attrib); virtual void issue_depth_write(const DepthWriteAttrib *attrib); @@ -293,7 +291,7 @@ protected: // GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports // Cur Texture State - TextureApplyAttrib::Mode _CurTexBlendMode; + TextureStage::Mode _CurTexBlendMode; D3DTEXTUREMAGFILTER _CurTexMagFilter; D3DTEXTUREMINFILTER _CurTexMinFilter; D3DTEXTUREMIPFILTER _CurTexMipFilter; @@ -332,7 +330,7 @@ public: void adjust_view_rect(int x, int y); INLINE void SetDXReady(bool stat) { _dx_ready = stat; } INLINE bool GetDXReady(void) { return _dx_ready;} - void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureApplyAttrib::Mode TexBlendMode,bool bJustEnable); + void DXGraphicsStateGuardian7::SetTextureBlendMode(TextureStage::Mode TexBlendMode,bool bJustEnable); void dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled); diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index c400ad782c..d333ad3c69 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -535,7 +535,7 @@ dx_init(void) { // must do SetTSS here because redundant states are filtered out by our code based on current values above, so // initial conditions must be correct - _CurTexBlendMode = TextureApplyAttrib::M_modulate; + _CurTexBlendMode = TextureStage::M_modulate; SetTextureBlendMode(_CurTexBlendMode,false); _texturing_enabled = false; _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); // disables texturing @@ -1607,9 +1607,7 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { Texture *tex = geom->get_texture(); if(tex !=NULL) { // set up the texture-rendering state - modify_state(RenderState::make - (TextureAttrib::make(tex), - TextureApplyAttrib::make(TextureApplyAttrib::M_modulate))); + modify_state(RenderState::make(TextureAttrib::make(tex))); tex_xsize = tex->get_x_size(); tex_ysize = tex->get_y_size(); } @@ -3178,6 +3176,9 @@ end_draw_primitives() { // responsibility of the calling function to later // call release_texture() with this same pointer (which // will also delete the pointer). +// +// This function should not be called directly to +// prepare a texture. Instead, call Texture::prepare(). //////////////////////////////////////////////////////////////////// TextureContext *DXGraphicsStateGuardian8:: prepare_texture(Texture *tex) { @@ -3192,7 +3193,7 @@ prepare_texture(Texture *tex) { //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::apply_texture -// Access: Public, Virtual +// Access: Public // Description: Makes the texture the currently available texture for // rendering. //////////////////////////////////////////////////////////////////// @@ -3790,13 +3791,13 @@ apply_fog(Fog *fog) { } } -void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexBlendMode,bool bCanJustEnable) { +void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureStage::Mode TexBlendMode,bool bCanJustEnable) { -/*class TextureApplyAttrib { +/*class TextureStage { enum Mode { M_modulate,M_decal,M_blend,M_replace,M_add}; */ - static D3DTEXTUREOP TexBlendColorOp1[/* TextureApplyAttrib::Mode maxval*/ 10] = + static D3DTEXTUREOP TexBlendColorOp1[/* TextureStage::Mode maxval*/ 10] = {D3DTOP_MODULATE,D3DTOP_BLENDTEXTUREALPHA,D3DTOP_MODULATE,D3DTOP_SELECTARG1,D3DTOP_ADD}; //if bCanJustEnable, then we only need to make sure ColorOp is turned on and set properly @@ -3810,7 +3811,7 @@ void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexB switch (TexBlendMode) { - case TextureApplyAttrib::M_modulate: + case TextureStage::M_modulate: // emulates GL_MODULATE glTexEnv mode // want to multiply tex-color*pixel color to emulate GL modulate blend (see glTexEnv) _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); @@ -3820,7 +3821,7 @@ void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; - case TextureApplyAttrib::M_decal: + case TextureStage::M_decal: // emulates GL_DECAL glTexEnv mode _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); @@ -3829,13 +3830,13 @@ void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); break; - case TextureApplyAttrib::M_replace: + case TextureStage::M_replace: _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); break; - case TextureApplyAttrib::M_add: + case TextureStage::M_add: _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); @@ -3845,7 +3846,7 @@ void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; - case TextureApplyAttrib::M_blend: + case TextureStage::M_blend: dxgsg8_cat.error() << "Impossible to emulate GL_BLEND in DX exactly " << (int) TexBlendMode << endl; /* @@ -4096,15 +4097,6 @@ issue_rescale_normal(const RescaleNormalAttrib *attrib) { } } -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian8::issue_texture_apply -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian8:: -issue_texture_apply(const TextureApplyAttrib *attrib) { -} - //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian8::issue_depth_test // Access: Public, Virtual diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h index f904135ffa..5a4b50f451 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.h +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.h @@ -34,7 +34,6 @@ #include "depthTestAttrib.h" #include "cullFaceAttrib.h" #include "renderModeAttrib.h" -#include "textureApplyAttrib.h" #include "fog.h" #include "pointerToArray.h" @@ -105,7 +104,7 @@ public: virtual void end_draw_primitives(); virtual TextureContext *prepare_texture(Texture *tex); - virtual void apply_texture(TextureContext *tc); + void apply_texture(TextureContext *tc); virtual void release_texture(TextureContext *tc); virtual VertexBufferContext *prepare_vertex_buffer(qpGeomVertexArrayData *data); @@ -132,7 +131,6 @@ public: virtual void issue_material(const MaterialAttrib *attrib); virtual void issue_render_mode(const RenderModeAttrib *attrib); virtual void issue_rescale_normal(const RescaleNormalAttrib *attrib); - virtual void issue_texture_apply(const TextureApplyAttrib *attrib); virtual void issue_alpha_test(const AlphaTestAttrib *attrib); virtual void issue_depth_test(const DepthTestAttrib *attrib); virtual void issue_depth_write(const DepthWriteAttrib *attrib); @@ -330,7 +328,7 @@ protected: //GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports // Cur Texture State - TextureApplyAttrib::Mode _CurTexBlendMode; + TextureStage::Mode _CurTexBlendMode; D3DTEXTUREFILTERTYPE _CurTexMagFilter,_CurTexMinFilter,_CurTexMipFilter; DWORD _CurTexAnisoDegree; Texture::WrapMode _CurTexWrapModeU,_CurTexWrapModeV; @@ -368,7 +366,7 @@ public: virtual TypeHandle force_init_type() {init_type(); return get_class_type();} INLINE void SetDXReady(bool status) { _bDXisReady = status; } INLINE bool GetDXReady(void) { return _bDXisReady;} - void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureApplyAttrib::Mode TexBlendMode,bool bJustEnable); + void DXGraphicsStateGuardian8::SetTextureBlendMode(TextureStage::Mode TexBlendMode,bool bJustEnable); void dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled); void reset_panda_gsg(void); diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx index e1a2007130..1267f36225 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.cxx @@ -486,7 +486,7 @@ dx_init(void) { // must do SetTSS here because redundant states are filtered out by our code based on current values above, so // initial conditions must be correct - _CurTexBlendMode = TextureApplyAttrib::M_modulate; + _CurTexBlendMode = TextureStage::M_modulate; SetTextureBlendMode(_CurTexBlendMode,false); _texturing_enabled = false; _pD3DDevice->SetTextureStageState(0,D3DTSS_COLOROP,D3DTOP_DISABLE); // disables texturing @@ -1527,9 +1527,7 @@ draw_sprite(GeomSprite *geom, GeomContext *gc) { Texture *tex = geom->get_texture(); if(tex !=NULL) { // set up the texture-rendering state - modify_state(RenderState::make - (TextureAttrib::make(tex), - TextureApplyAttrib::make(TextureApplyAttrib::M_modulate))); + modify_state(RenderState::make(TextureAttrib::make(tex))); tex_xsize = tex->get_x_size(); tex_ysize = tex->get_y_size(); } @@ -2581,7 +2579,7 @@ prepare_texture(Texture *tex) { //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian9::apply_texture -// Access: Public, Virtual +// Access: Public // Description: Makes the texture the currently available texture for // rendering. //////////////////////////////////////////////////////////////////// @@ -2974,13 +2972,13 @@ apply_fog(Fog *fog) { } } -void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureApplyAttrib::Mode TexBlendMode,bool bCanJustEnable) { +void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureStage::Mode TexBlendMode,bool bCanJustEnable) { -/*class TextureApplyAttrib { +/*class TextureStage { enum Mode { M_modulate,M_decal,M_blend,M_replace,M_add}; */ - static D3DTEXTUREOP TexBlendColorOp1[/* TextureApplyAttrib::Mode maxval*/ 10] = + static D3DTEXTUREOP TexBlendColorOp1[/* TextureStage::Mode maxval*/ 10] = {D3DTOP_MODULATE,D3DTOP_BLENDTEXTUREALPHA,D3DTOP_MODULATE,D3DTOP_SELECTARG1,D3DTOP_ADD}; //if bCanJustEnable, then we only need to make sure ColorOp is turned on and set properly @@ -2996,7 +2994,7 @@ void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureApplyAttrib::Mode TexB switch (TexBlendMode) { - case TextureApplyAttrib::M_modulate: + case TextureStage::M_modulate: // emulates GL_MODULATE glTexEnv mode // want to multiply tex-color*pixel color to emulate GL modulate blend (see glTexEnv) /* @@ -3017,7 +3015,7 @@ void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pD3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_MODULATE); //dxgsg9_cat.info() << "--------------modulating--------------" << endl; break; - case TextureApplyAttrib::M_decal: + case TextureStage::M_decal: // emulates GL_DECAL glTexEnv mode _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); @@ -3026,13 +3024,13 @@ void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE ); break; - case TextureApplyAttrib::M_replace: + case TextureStage::M_replace: _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 ); _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE ); break; - case TextureApplyAttrib::M_add: + case TextureStage::M_add: _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG1, D3DTA_TEXTURE ); _pD3DDevice->SetTextureStageState( 0, D3DTSS_COLORARG2, D3DTA_DIFFUSE ); @@ -3042,7 +3040,7 @@ void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureApplyAttrib::Mode TexB _pD3DDevice->SetTextureStageState( 0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE ); break; - case TextureApplyAttrib::M_blend: + case TextureStage::M_blend: dxgsg9_cat.error() << "Impossible to emulate GL_BLEND in DX exactly " << (int) TexBlendMode << endl; /* @@ -3281,15 +3279,6 @@ issue_rescale_normal(const RescaleNormalAttrib *attrib) { } } -//////////////////////////////////////////////////////////////////// -// Function: DXGraphicsStateGuardian9::issue_texture_apply -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void DXGraphicsStateGuardian9:: -issue_texture_apply(const TextureApplyAttrib *attrib) { -} - //////////////////////////////////////////////////////////////////// // Function: DXGraphicsStateGuardian9::issue_depth_test // Access: Public, Virtual diff --git a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h index 04fc09f30d..07c7a30120 100755 --- a/panda/src/dxgsg9/dxGraphicsStateGuardian9.h +++ b/panda/src/dxgsg9/dxGraphicsStateGuardian9.h @@ -34,7 +34,6 @@ #include "material.h" #include "depthTestAttrib.h" #include "renderModeAttrib.h" -#include "textureApplyAttrib.h" #include "fog.h" #include "pointerToArray.h" @@ -91,7 +90,7 @@ public: virtual void draw_sphere(GeomSphere *geom, GeomContext *gc); virtual TextureContext *prepare_texture(Texture *tex); - virtual void apply_texture(TextureContext *tc, int index=0); + void apply_texture(TextureContext *tc, int index); virtual void release_texture(TextureContext *tc); virtual void framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, @@ -109,7 +108,6 @@ public: virtual void issue_material(const MaterialAttrib *attrib); virtual void issue_render_mode(const RenderModeAttrib *attrib); virtual void issue_rescale_normal(const RescaleNormalAttrib *attrib); - virtual void issue_texture_apply(const TextureApplyAttrib *attrib); virtual void issue_alpha_test(const AlphaTestAttrib *attrib); virtual void issue_depth_test(const DepthTestAttrib *attrib); virtual void issue_depth_write(const DepthWriteAttrib *attrib); @@ -296,7 +294,7 @@ protected: //GraphicsChannel *_panda_gfx_channel; // cache the 1 channel dx supports // Cur Texture State - TextureApplyAttrib::Mode _CurTexBlendMode; + TextureStage::Mode _CurTexBlendMode; D3DTEXTUREFILTERTYPE _CurTexMagFilter,_CurTexMinFilter,_CurTexMipFilter; DWORD _CurTexAnisoDegree; Texture::WrapMode _CurTexWrapModeU,_CurTexWrapModeV; @@ -332,7 +330,7 @@ public: virtual TypeHandle force_init_type() {init_type(); return get_class_type();} INLINE void SetDXReady(bool status) { _bDXisReady = status; } INLINE bool GetDXReady(void) { return _bDXisReady;} - void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureApplyAttrib::Mode TexBlendMode,bool bJustEnable); + void DXGraphicsStateGuardian9::SetTextureBlendMode(TextureStage::Mode TexBlendMode,bool bJustEnable); void dx_cleanup(bool bRestoreDisplayMode,bool bAtExitFnCalled); void reset_panda_gsg(void); diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 09680a22f0..3923e10aee 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1439,9 +1439,7 @@ draw_sprite(GeomSprite *geom, GeomContext *) { Texture *tex = geom->get_texture(); if(tex != NULL) { // set up the texture-rendering state - modify_state(RenderState::make - (TextureAttrib::make(tex), - TextureApplyAttrib::make(TextureApplyAttrib::M_modulate))); + modify_state(RenderState::make(TextureAttrib::make(tex))); tex_x_size = tex->get_x_size(); tex_y_size = tex->get_y_size(); } @@ -2759,12 +2757,12 @@ end_draw_primitives() { //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::prepare_texture // Access: Public, Virtual -// Description: Creates a new retained-mode representation of the -// given texture, and returns a newly-allocated -// TextureContext pointer to reference it. It is the -// responsibility of the calling function to later -// call release_texture() with this same pointer (which -// will also delete the pointer). +// Description: Creates whatever structures the GSG requires to +// represent the texture internally, and returns a +// newly-allocated TextureContext object with this data. +// It is the responsibility of the calling function to +// later call release_texture() with this same pointer +// (which will also delete the pointer). // // This function should not be called directly to // prepare a texture. Instead, call Texture::prepare(). @@ -2773,44 +2771,12 @@ TextureContext *CLP(GraphicsStateGuardian):: prepare_texture(Texture *tex) { CLP(TextureContext) *gtc = new CLP(TextureContext)(tex); GLP(GenTextures)(1, >c->_index); - - bind_texture(gtc); - GLP(PrioritizeTextures)(1, >c->_index, >c->_priority); - specify_texture(tex); - apply_texture_immediate(gtc, tex); - report_my_gl_errors(); + + apply_texture(gtc); return gtc; } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::apply_texture -// Access: Public, Virtual -// Description: Makes the texture the currently available texture for -// rendering. -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -apply_texture(TextureContext *tc, int index) { - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - - add_to_texture_record(gtc); - bind_texture(gtc); - - int dirty = gtc->get_dirty_flags(); - if ((dirty & (Texture::DF_wrap | Texture::DF_filter | Texture::DF_border)) != 0) { - // We need to re-specify the texture properties. - specify_texture(gtc->_texture); - } - if ((dirty & (Texture::DF_image | Texture::DF_mipmap | Texture::DF_border)) != 0) { - // We need to re-apply the image. - apply_texture_immediate(gtc, gtc->_texture); - } - - gtc->clear_dirty_flags(); - - report_my_gl_errors(); -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::release_texture // Access: Public, Virtual @@ -3283,7 +3249,14 @@ framebuffer_copy_to_texture(Texture *tex, int z, const DisplayRegion *dr, TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); nassertv(tc != (TextureContext *)NULL); - bind_texture(tc); + + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + GLenum target = get_texture_target(tex->get_texture_type()); + if (target == GL_NONE) { + // Invalid texture, can't copy to it. + return; + } + GLP(BindTexture)(target, gtc->_index); if (z >= 0) { // Copy to a cube map face. @@ -3439,7 +3412,8 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, // Access: Public, Virtual // Description: //////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian)::apply_material(const Material *material) { +void CLP(GraphicsStateGuardian):: +apply_material(const Material *material) { GLenum face = material->get_twoside() ? GL_FRONT_AND_BACK : GL_FRONT; GLP(Materialfv)(face, GL_SPECULAR, material->get_specular().get_data()); @@ -3783,18 +3757,6 @@ issue_rescale_normal(const RescaleNormalAttrib *attrib) { report_my_gl_errors(); } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::issue_texture_apply -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -issue_texture_apply(const TextureApplyAttrib *) { - // This attrib is no longer used; it is replaced by the parameters - // within TextureStage. - return; -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::issue_color_write // Access: Public, Virtual @@ -4391,501 +4353,6 @@ set_read_buffer(const RenderBuffer &rb) { } -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::bind_texture -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -bind_texture(TextureContext *tc) { - CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); - report_my_gl_errors(); - -#ifdef GSG_VERBOSE - Texture *tex = tc->_texture; - GLCAT.spam() - << "glBindTexture(): " << tex->get_name() << "(" << (int)gtc->_index - << ")" << endl; -#endif - - GLenum target = get_texture_target(tc->_texture->get_texture_type()); - if (target != GL_NONE) { - GLP(BindTexture)(target, gtc->_index); - } - - report_my_gl_errors(); -} - -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::specify_texture -// Access: Protected -// Description: -//////////////////////////////////////////////////////////////////// -void CLP(GraphicsStateGuardian):: -specify_texture(Texture *tex) { - GLenum target = get_texture_target(tex->get_texture_type()); - if (target == GL_NONE) { - // Unsupported target (e.g. 3-d texturing on GL 1.1). - return; - } - - GLP(TexParameteri)(target, GL_TEXTURE_WRAP_S, - get_texture_wrap_mode(tex->get_wrap_u())); - if (target != GL_TEXTURE_1D) { - GLP(TexParameteri)(target, GL_TEXTURE_WRAP_T, - get_texture_wrap_mode(tex->get_wrap_v())); - } - if (target == GL_TEXTURE_3D) { - GLP(TexParameteri)(target, GL_TEXTURE_WRAP_R, - get_texture_wrap_mode(tex->get_wrap_w())); - } - - Colorf border_color = tex->get_border_color(); - GLP(TexParameterfv)(target, GL_TEXTURE_BORDER_COLOR, - border_color.get_data()); - - Texture::FilterType minfilter = tex->get_minfilter(); - Texture::FilterType magfilter = tex->get_magfilter(); - bool uses_mipmaps = tex->uses_mipmaps() && !CLP(ignore_mipmaps); - -#ifndef NDEBUG - if (CLP(force_mipmaps)) { - minfilter = Texture::FT_linear_mipmap_linear; - magfilter = Texture::FT_linear; - uses_mipmaps = true; - } -#endif - - if (_supports_generate_mipmap && - (auto_generate_mipmaps || !tex->might_have_ram_image())) { - // If the hardware can automatically generate mipmaps, ask it to - // do so now, but only if the texture requires them. - GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, uses_mipmaps); - - } else if (!tex->might_have_ram_image()) { - // If the hardware can't automatically generate mipmaps, but it's - // a dynamically generated texture (that is, the RAM image isn't - // available so it didn't pass through the CPU), then we'd better - // not try to enable mipmap filtering, since we can't generate - // mipmaps. - uses_mipmaps = false; - } - - GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, - get_texture_filter_type(minfilter, !uses_mipmaps)); - GLP(TexParameteri)(target, GL_TEXTURE_MAG_FILTER, - get_texture_filter_type(magfilter, true)); - - report_my_gl_errors(); -} - -#ifndef NDEBUG -//////////////////////////////////////////////////////////////////// -// Function: compute_gl_image_size -// Description: Calculates how many bytes GL will expect to read for -// a texture image, based on the number of pixels and -// the GL format and type. This is only used for -// debugging. -//////////////////////////////////////////////////////////////////// -static int -compute_gl_image_size(int x_size, int y_size, int z_size, - int external_format, int type) { - int num_components = 0; - switch (external_format) { - case GL_COLOR_INDEX: - case GL_STENCIL_INDEX: - case GL_DEPTH_COMPONENT: - case GL_RED: - case GL_GREEN: - case GL_BLUE: - case GL_ALPHA: - case GL_LUMINANCE: - num_components = 1; - break; - - case GL_LUMINANCE_ALPHA: - num_components = 2; - break; - - case GL_BGR: - case GL_RGB: - num_components = 3; - break; - - case GL_BGRA: - case GL_RGBA: - num_components = 4; - break; - } - - int pixel_width = 0; - switch (type) { - case GL_UNSIGNED_BYTE: - pixel_width = 1 * num_components; - break; - - case GL_UNSIGNED_SHORT: - pixel_width = 2 * num_components; - break; - - case GL_UNSIGNED_BYTE_3_3_2: - nassertr(num_components == 3, 0); - pixel_width = 1; - break; - - case GL_FLOAT: - pixel_width = 4 * num_components; - break; - } - - return x_size * y_size * z_size * pixel_width; -} -#endif // NDEBUG - -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::apply_texture_immediate -// Access: Protected -// Description: Sends the texture image to GL. This can be used to -// render a texture in immediate mode, or as part of the -// process of creating a GL texture object. -// -// The return value is true if successful, or false if -// the texture has no image. -//////////////////////////////////////////////////////////////////// -bool CLP(GraphicsStateGuardian):: -apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex) { - CPTA_uchar image = tex->get_ram_image(); - if (image.is_null()) { - return false; - } - - int width = tex->get_x_size(); - int height = tex->get_y_size(); - int depth = tex->get_z_size(); - - GLint internal_format = get_internal_image_format(tex->get_format()); - GLint external_format = get_external_image_format(tex->get_format()); - GLenum component_type = get_component_type(tex->get_component_type()); - - // Ensure that the texture fits within the GL's specified limits. - int max_dimension; - switch (tex->get_texture_type()) { - case Texture::TT_3d_texture: - max_dimension = _max_3d_texture_dimension; - break; - - case Texture::TT_cube_map: - max_dimension = _max_cube_map_dimension; - break; - - default: - max_dimension = _max_texture_dimension; - } - - if (max_dimension == 0) { - // Guess this GL doesn't support cube mapping/3d textures. - report_my_gl_errors(); - return false; - } - - int texel_size = tex->get_num_components() * tex->get_component_width(); - - // If it doesn't fit, we have to reduce it on-the-fly. This is kind - // of expensive and it doesn't look great; it would have been better - // if the user had specified max-texture-dimension to reduce the - // texture at load time instead. Of course, the user doesn't always - // know ahead of time what the hardware limits are. - if (max_dimension > 0) { - if (width > max_dimension) { - int byte_chunk = texel_size; - int stride = 1; - int new_width = width; - while (new_width > max_dimension) { - stride <<= 1; - new_width >>= 1; - } - GLCAT.info() - << "Reducing width of " << tex->get_name() - << " from " << width << " to " << new_width << "\n"; - image = reduce_image(image, byte_chunk, stride); - width = new_width; - } - if (height > max_dimension) { - int byte_chunk = width * texel_size; - int stride = 1; - int new_height = height; - while (new_height > max_dimension) { - stride <<= 1; - new_height >>= 1; - } - GLCAT.info() - << "Reducing height of " << tex->get_name() - << " from " << height << " to " << new_height << "\n"; - image = reduce_image(image, byte_chunk, stride); - height = new_height; - } - if (depth > max_dimension) { - int byte_chunk = height * width * texel_size; - int stride = 1; - int new_depth = depth; - while (new_depth > max_dimension) { - stride <<= 1; - new_depth >>= 1; - } - GLCAT.info() - << "Reducing depth of " << tex->get_name() - << " from " << depth << " to " << new_depth << "\n"; - image = reduce_image(image, byte_chunk, stride); - depth = new_depth; - } - } - - if (!_supports_bgr) { - // If the GL doesn't claim to support BGR, we may have to reverse - // the component ordering of the image. - image = fix_component_ordering(image, external_format, tex); - } - -#ifndef NDEBUG - int wanted_size = - compute_gl_image_size(width, height, depth, external_format, component_type); - nassertr(wanted_size == (int)image.size(), false); -#endif // NDEBUG - - GLP(PixelStorei)(GL_UNPACK_ALIGNMENT, 1); - - bool uses_mipmaps = (tex->uses_mipmaps() && !CLP(ignore_mipmaps)) || CLP(force_mipmaps); - -#ifndef NDEBUG - if (CLP(force_mipmaps)) { - uses_mipmaps = true; - } -#endif - - bool success = true; - - if (tex->get_texture_type() == Texture::TT_cube_map) { - // A cube map must load six different 2-d images (which are stored - // as the six pages of the system ram image). - if (!_supports_cube_map) { - report_my_gl_errors(); - return false; - } - - size_t page_size = height * width * texel_size; - const unsigned char *image_base = image; - - success = success && upload_texture_image - (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_X, - internal_format, width, height, depth, external_format, component_type, - image_base); - image_base += page_size; - - success = success && upload_texture_image - (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, - internal_format, width, height, depth, external_format, component_type, - image_base); - image_base += page_size; - - success = success && upload_texture_image - (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, - internal_format, width, height, depth, external_format, component_type, - image_base); - image_base += page_size; - - success = success && upload_texture_image - (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, - internal_format, width, height, depth, external_format, component_type, - image_base); - image_base += page_size; - - success = success && upload_texture_image - (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, - internal_format, width, height, depth, external_format, component_type, - image_base); - image_base += page_size; - - success = success && upload_texture_image - (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, - internal_format, width, height, depth, external_format, component_type, - image_base); - image_base += page_size; - - nassertr((size_t)(image_base - image) == image.size(), false); - - } else { - // Any other kind of texture can be loaded all at once. - success = upload_texture_image - (gtc, uses_mipmaps, get_texture_target(tex->get_texture_type()), - internal_format, width, height, depth, external_format, component_type, - image); - } - - if (success) { - gtc->_already_applied = true; - gtc->_internal_format = internal_format; - gtc->_width = width; - gtc->_height = height; - gtc->_depth = depth; - -#ifndef NDEBUG - if (uses_mipmaps && CLP(save_mipmaps)) { - save_mipmap_images(tex); - } -#endif - - report_my_gl_errors(); - return true; - } - - report_my_gl_errors(); - return false; -} - -//////////////////////////////////////////////////////////////////// -// Function: GLGraphicsStateGuardian::upload_texture_image -// Access: Protected -// Description: Loads a texture image, or one page of a cube map -// image, from system RAM to texture memory. -//////////////////////////////////////////////////////////////////// -bool CLP(GraphicsStateGuardian):: -upload_texture_image(CLP(TextureContext) *gtc, - bool uses_mipmaps, - GLenum target, GLint internal_format, - int width, int height, int depth, - GLint external_format, GLenum component_type, - const unsigned char *image) { - if (target == GL_NONE) { - // Unsupported target (e.g. 3-d texturing on GL 1.1). - return false; - } - PStatTimer timer(_load_texture_pcollector); - - if (uses_mipmaps) { -#ifndef NDEBUG - if (CLP(show_mipmaps) && target == GL_TEXTURE_2D) { - build_phony_mipmaps(gtc->_texture); - report_my_gl_errors(); - return true; - - } else -#endif - if (!_supports_generate_mipmap || !auto_generate_mipmaps) { - // We only need to build the mipmaps by hand if the GL - // doesn't support generating them automatically. - bool success = true; -#ifdef DO_PSTATS - _data_transferred_pcollector.add_level(get_external_texture_bytes(width, height, depth, external_format, component_type) * 4 / 3); -#endif - switch (target) { - case GL_TEXTURE_1D: - GLUP(Build1DMipmaps)(target, internal_format, width, - external_format, component_type, image); - break; - - case GL_TEXTURE_3D: -#ifdef GLU_VERSION_1_3 - GLUP(Build3DMipmaps)(target, internal_format, - width, height, depth, - external_format, component_type, image); -#else // GLU_VERSION_1_3 - // Prior to GLU 1.3, there was no gluBuild3DMipmaps() call. - // Just fall through and load the texture without mipmaps. - GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - success = false; -#endif // GLU_VERSION_1_3 - break; - - default: - GLUP(Build2DMipmaps)(target, internal_format, - width, height, - external_format, component_type, image); - } - - report_my_gl_errors(); - if (success) { - return true; - } - } - } - - if (!gtc->_already_applied || - gtc->_internal_format != internal_format || - gtc->_width != width || - gtc->_height != height || - gtc->_depth != depth) { - // We need to reload a new image. -#ifdef DO_PSTATS - _data_transferred_pcollector.add_level(get_external_texture_bytes(width, height, depth, external_format, component_type)); -#endif - switch (target) { - case GL_TEXTURE_1D: - GLP(TexImage1D)(target, 0, internal_format, - width, 0, - external_format, component_type, image); - break; - - case GL_TEXTURE_3D: - if (_supports_3d_texture) { - _glTexImage3D(target, 0, internal_format, - width, height, depth, 0, - external_format, component_type, image); - } else { - report_my_gl_errors(); - return false; - } - break; - - default: - GLP(TexImage2D)(target, 0, internal_format, - width, height, 0, - external_format, component_type, image); - } - - } else { - // We can reload the image over the previous image, possibly - // saving on texture memory fragmentation. - switch (target) { - case GL_TEXTURE_1D: - GLP(TexSubImage1D)(target, 0, 0, width, - external_format, component_type, image); - break; - - case GL_TEXTURE_3D: - if (_supports_3d_texture) { - _glTexSubImage3D(target, 0, 0, 0, 0, width, height, depth, - external_format, component_type, image); - } else { - report_my_gl_errors(); - return false; - } - break; - - default: - GLP(TexSubImage2D)(target, 0, 0, 0, width, height, - external_format, component_type, image); - break; - } - } - - // Report the error message explicitly if the GL texture creation - // failed. - GLenum error_code = GLP(GetError)(); - if (error_code != GL_NO_ERROR) { - const GLubyte *error_string = GLUP(ErrorString)(error_code); - GLCAT.error() - << "GL texture creation failed for " << gtc->_texture->get_name(); - if (error_string != (const GLubyte *)NULL) { - GLCAT.error(false) - << " : " << error_string; - } - GLCAT.error(false) - << "\n"; - } - - return true; -} - //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::get_numeric_type @@ -6378,6 +5845,509 @@ do_issue_texture() { report_my_gl_errors(); } +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::specify_texture +// Access: Protected +// Description: Specifies the texture parameters. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +specify_texture(Texture *tex) { + GLenum target = get_texture_target(tex->get_texture_type()); + if (target == GL_NONE) { + // Unsupported target (e.g. 3-d texturing on GL 1.1). + return; + } + + GLP(TexParameteri)(target, GL_TEXTURE_WRAP_S, + get_texture_wrap_mode(tex->get_wrap_u())); + if (target != GL_TEXTURE_1D) { + GLP(TexParameteri)(target, GL_TEXTURE_WRAP_T, + get_texture_wrap_mode(tex->get_wrap_v())); + } + if (target == GL_TEXTURE_3D) { + GLP(TexParameteri)(target, GL_TEXTURE_WRAP_R, + get_texture_wrap_mode(tex->get_wrap_w())); + } + + Colorf border_color = tex->get_border_color(); + GLP(TexParameterfv)(target, GL_TEXTURE_BORDER_COLOR, + border_color.get_data()); + + Texture::FilterType minfilter = tex->get_minfilter(); + Texture::FilterType magfilter = tex->get_magfilter(); + bool uses_mipmaps = tex->uses_mipmaps() && !CLP(ignore_mipmaps); + +#ifndef NDEBUG + if (CLP(force_mipmaps)) { + minfilter = Texture::FT_linear_mipmap_linear; + magfilter = Texture::FT_linear; + uses_mipmaps = true; + } +#endif + + if (_supports_generate_mipmap && + (auto_generate_mipmaps || !tex->might_have_ram_image())) { + // If the hardware can automatically generate mipmaps, ask it to + // do so now, but only if the texture requires them. + GLP(TexParameteri)(target, GL_GENERATE_MIPMAP, uses_mipmaps); + + } else if (!tex->might_have_ram_image()) { + // If the hardware can't automatically generate mipmaps, but it's + // a dynamically generated texture (that is, the RAM image isn't + // available so it didn't pass through the CPU), then we'd better + // not try to enable mipmap filtering, since we can't generate + // mipmaps. + uses_mipmaps = false; + } + + GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, + get_texture_filter_type(minfilter, !uses_mipmaps)); + GLP(TexParameteri)(target, GL_TEXTURE_MAG_FILTER, + get_texture_filter_type(magfilter, true)); + + report_my_gl_errors(); +} + +#ifndef NDEBUG +//////////////////////////////////////////////////////////////////// +// Function: compute_gl_image_size +// Description: Calculates how many bytes GL will expect to read for +// a texture image, based on the number of pixels and +// the GL format and type. This is only used for +// debugging. +//////////////////////////////////////////////////////////////////// +static int +compute_gl_image_size(int x_size, int y_size, int z_size, + int external_format, int type) { + int num_components = 0; + switch (external_format) { + case GL_COLOR_INDEX: + case GL_STENCIL_INDEX: + case GL_DEPTH_COMPONENT: + case GL_RED: + case GL_GREEN: + case GL_BLUE: + case GL_ALPHA: + case GL_LUMINANCE: + num_components = 1; + break; + + case GL_LUMINANCE_ALPHA: + num_components = 2; + break; + + case GL_BGR: + case GL_RGB: + num_components = 3; + break; + + case GL_BGRA: + case GL_RGBA: + num_components = 4; + break; + } + + int pixel_width = 0; + switch (type) { + case GL_UNSIGNED_BYTE: + pixel_width = 1 * num_components; + break; + + case GL_UNSIGNED_SHORT: + pixel_width = 2 * num_components; + break; + + case GL_UNSIGNED_BYTE_3_3_2: + nassertr(num_components == 3, 0); + pixel_width = 1; + break; + + case GL_FLOAT: + pixel_width = 4 * num_components; + break; + } + + return x_size * y_size * z_size * pixel_width; +} +#endif // NDEBUG + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::apply_texture +// Access: Protected +// Description: Updates OpenGL with the current information for this +// texture, and makes it the current texture available +// for rendering. +//////////////////////////////////////////////////////////////////// +void CLP(GraphicsStateGuardian):: +apply_texture(TextureContext *tc) { + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + + add_to_texture_record(gtc); + GLenum target = get_texture_target(gtc->_texture->get_texture_type()); + if (target == GL_NONE) { + return; + } + GLP(BindTexture)(target, gtc->_index); + + int dirty = gtc->get_dirty_flags(); + if ((dirty & (Texture::DF_wrap | Texture::DF_filter | Texture::DF_border)) != 0) { + // We need to re-specify the texture properties. + specify_texture(gtc->_texture); + } + if ((dirty & (Texture::DF_image | Texture::DF_mipmap)) != 0) { + // We need to re-upload the image. + upload_texture(gtc); + } + + gtc->clear_dirty_flags(); + + report_my_gl_errors(); +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::upload_texture +// Access: Protected +// Description: Uploads the entire texture image to OpenGL, including +// all pages. +// +// The return value is true if successful, or false if +// the texture has no image. +//////////////////////////////////////////////////////////////////// +bool CLP(GraphicsStateGuardian):: +upload_texture(CLP(TextureContext) *gtc) { + Texture *tex = gtc->_texture; + CPTA_uchar image = tex->get_ram_image(); + if (image.is_null()) { + return false; + } + + int width = tex->get_x_size(); + int height = tex->get_y_size(); + int depth = tex->get_z_size(); + + GLint internal_format = get_internal_image_format(tex->get_format()); + GLint external_format = get_external_image_format(tex->get_format()); + GLenum component_type = get_component_type(tex->get_component_type()); + + // Ensure that the texture fits within the GL's specified limits. + int max_dimension; + switch (tex->get_texture_type()) { + case Texture::TT_3d_texture: + max_dimension = _max_3d_texture_dimension; + break; + + case Texture::TT_cube_map: + max_dimension = _max_cube_map_dimension; + break; + + default: + max_dimension = _max_texture_dimension; + } + + if (max_dimension == 0) { + // Guess this GL doesn't support cube mapping/3d textures. + report_my_gl_errors(); + return false; + } + + int texel_size = tex->get_num_components() * tex->get_component_width(); + + // If it doesn't fit, we have to reduce it on-the-fly. This is kind + // of expensive and it doesn't look great; it would have been better + // if the user had specified max-texture-dimension to reduce the + // texture at load time instead. Of course, the user doesn't always + // know ahead of time what the hardware limits are. + if (max_dimension > 0) { + if (width > max_dimension) { + int byte_chunk = texel_size; + int stride = 1; + int new_width = width; + while (new_width > max_dimension) { + stride <<= 1; + new_width >>= 1; + } + GLCAT.info() + << "Reducing width of " << tex->get_name() + << " from " << width << " to " << new_width << "\n"; + image = reduce_image(image, byte_chunk, stride); + width = new_width; + } + if (height > max_dimension) { + int byte_chunk = width * texel_size; + int stride = 1; + int new_height = height; + while (new_height > max_dimension) { + stride <<= 1; + new_height >>= 1; + } + GLCAT.info() + << "Reducing height of " << tex->get_name() + << " from " << height << " to " << new_height << "\n"; + image = reduce_image(image, byte_chunk, stride); + height = new_height; + } + if (depth > max_dimension) { + int byte_chunk = height * width * texel_size; + int stride = 1; + int new_depth = depth; + while (new_depth > max_dimension) { + stride <<= 1; + new_depth >>= 1; + } + GLCAT.info() + << "Reducing depth of " << tex->get_name() + << " from " << depth << " to " << new_depth << "\n"; + image = reduce_image(image, byte_chunk, stride); + depth = new_depth; + } + } + + if (!_supports_bgr) { + // If the GL doesn't claim to support BGR, we may have to reverse + // the component ordering of the image. + image = fix_component_ordering(image, external_format, tex); + } + +#ifndef NDEBUG + int wanted_size = + compute_gl_image_size(width, height, depth, external_format, component_type); + nassertr(wanted_size == (int)image.size(), false); +#endif // NDEBUG + + GLP(PixelStorei)(GL_UNPACK_ALIGNMENT, 1); + + bool uses_mipmaps = (tex->uses_mipmaps() && !CLP(ignore_mipmaps)) || CLP(force_mipmaps); + +#ifndef NDEBUG + if (CLP(force_mipmaps)) { + uses_mipmaps = true; + } +#endif + + bool success = true; + + if (tex->get_texture_type() == Texture::TT_cube_map) { + // A cube map must load six different 2-d images (which are stored + // as the six pages of the system ram image). + if (!_supports_cube_map) { + report_my_gl_errors(); + return false; + } + + size_t page_size = height * width * texel_size; + const unsigned char *image_base = image; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_X, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_X, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_Y, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_POSITIVE_Z, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + success = success && upload_texture_image + (gtc, uses_mipmaps, GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, + internal_format, width, height, depth, external_format, component_type, + image_base); + image_base += page_size; + + nassertr((size_t)(image_base - image) == image.size(), false); + + } else { + // Any other kind of texture can be loaded all at once. + success = upload_texture_image + (gtc, uses_mipmaps, get_texture_target(tex->get_texture_type()), + internal_format, width, height, depth, external_format, component_type, + image); + } + + if (success) { + gtc->_already_applied = true; + gtc->_internal_format = internal_format; + gtc->_width = width; + gtc->_height = height; + gtc->_depth = depth; + +#ifndef NDEBUG + if (uses_mipmaps && CLP(save_mipmaps)) { + save_mipmap_images(tex); + } +#endif + + report_my_gl_errors(); + return true; + } + + report_my_gl_errors(); + return false; +} + +//////////////////////////////////////////////////////////////////// +// Function: GLGraphicsStateGuardian::upload_texture_image +// Access: Protected +// Description: Loads a texture image, or one page of a cube map +// image, from system RAM to texture memory. +//////////////////////////////////////////////////////////////////// +bool CLP(GraphicsStateGuardian):: +upload_texture_image(CLP(TextureContext) *gtc, + bool uses_mipmaps, + GLenum target, GLint internal_format, + int width, int height, int depth, + GLint external_format, GLenum component_type, + const unsigned char *image) { + if (target == GL_NONE) { + // Unsupported target (e.g. 3-d texturing on GL 1.1). + return false; + } + PStatTimer timer(_load_texture_pcollector); + + if (uses_mipmaps) { +#ifndef NDEBUG + if (CLP(show_mipmaps) && target == GL_TEXTURE_2D) { + build_phony_mipmaps(gtc->_texture); + report_my_gl_errors(); + return true; + + } else +#endif + if (!_supports_generate_mipmap || !auto_generate_mipmaps) { + // We only need to build the mipmaps by hand if the GL + // doesn't support generating them automatically. + bool success = true; +#ifdef DO_PSTATS + _data_transferred_pcollector.add_level(get_external_texture_bytes(width, height, depth, external_format, component_type) * 4 / 3); +#endif + switch (target) { + case GL_TEXTURE_1D: + GLUP(Build1DMipmaps)(target, internal_format, width, + external_format, component_type, image); + break; + + case GL_TEXTURE_3D: +#ifdef GLU_VERSION_1_3 + GLUP(Build3DMipmaps)(target, internal_format, + width, height, depth, + external_format, component_type, image); +#else // GLU_VERSION_1_3 + // Prior to GLU 1.3, there was no gluBuild3DMipmaps() call. + // Just fall through and load the texture without mipmaps. + GLP(TexParameteri)(target, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + success = false; +#endif // GLU_VERSION_1_3 + break; + + default: + GLUP(Build2DMipmaps)(target, internal_format, + width, height, + external_format, component_type, image); + } + + report_my_gl_errors(); + if (success) { + return true; + } + } + } + + if (!gtc->_already_applied || + gtc->_internal_format != internal_format || + gtc->_width != width || + gtc->_height != height || + gtc->_depth != depth) { + // We need to reload a new image. +#ifdef DO_PSTATS + _data_transferred_pcollector.add_level(get_external_texture_bytes(width, height, depth, external_format, component_type)); +#endif + switch (target) { + case GL_TEXTURE_1D: + GLP(TexImage1D)(target, 0, internal_format, + width, 0, + external_format, component_type, image); + break; + + case GL_TEXTURE_3D: + if (_supports_3d_texture) { + _glTexImage3D(target, 0, internal_format, + width, height, depth, 0, + external_format, component_type, image); + } else { + report_my_gl_errors(); + return false; + } + break; + + default: + GLP(TexImage2D)(target, 0, internal_format, + width, height, 0, + external_format, component_type, image); + } + + } else { + // We can reload the image over the previous image, possibly + // saving on texture memory fragmentation. + switch (target) { + case GL_TEXTURE_1D: + GLP(TexSubImage1D)(target, 0, 0, width, + external_format, component_type, image); + break; + + case GL_TEXTURE_3D: + if (_supports_3d_texture) { + _glTexSubImage3D(target, 0, 0, 0, 0, width, height, depth, + external_format, component_type, image); + } else { + report_my_gl_errors(); + return false; + } + break; + + default: + GLP(TexSubImage2D)(target, 0, 0, 0, width, height, + external_format, component_type, image); + break; + } + } + + // Report the error message explicitly if the GL texture creation + // failed. + GLenum error_code = GLP(GetError)(); + if (error_code != GL_NO_ERROR) { + const GLubyte *error_string = GLUP(ErrorString)(error_code); + GLCAT.error() + << "GL texture creation failed for " << gtc->_texture->get_name(); + if (error_string != (const GLubyte *)NULL) { + GLCAT.error(false) + << " : " << error_string; + } + GLCAT.error(false) + << "\n"; + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: GLGraphicsStateGuardian::do_point_size // Access: Protected diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 6ca2e5c101..38cb4d336c 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -29,7 +29,6 @@ #include "texMatrixAttrib.h" #include "texGenAttrib.h" #include "textureStage.h" -#include "textureApplyAttrib.h" #include "antialiasAttrib.h" #include "renderModeAttrib.h" #include "pointerToArray.h" @@ -108,7 +107,6 @@ public: INLINE bool draw_display_list(GeomContext *gc); virtual TextureContext *prepare_texture(Texture *tex); - virtual void apply_texture(TextureContext *tc, int index=0); virtual void release_texture(TextureContext *tc); virtual GeomContext *prepare_geom(Geom *geom); @@ -141,7 +139,6 @@ public: virtual void issue_render_mode(const RenderModeAttrib *attrib); virtual void issue_antialias(const AntialiasAttrib *); virtual void issue_rescale_normal(const RescaleNormalAttrib *attrib); - virtual void issue_texture_apply(const TextureApplyAttrib *attrib); virtual void issue_color_write(const ColorWriteAttrib *attrib); virtual void issue_depth_test(const DepthTestAttrib *attrib); virtual void issue_alpha_test(const AlphaTestAttrib *attrib); @@ -235,15 +232,6 @@ protected: void set_draw_buffer(const RenderBuffer &rb); void set_read_buffer(const RenderBuffer &rb); - void bind_texture(TextureContext *tc); - void specify_texture(Texture *tex); - bool apply_texture_immediate(CLP(TextureContext) *gtc, Texture *tex); - bool upload_texture_image(CLP(TextureContext) *gtc, bool uses_mipmaps, - GLenum target, GLint internal_format, - int width, int height, int depth, - GLint external_format, GLenum component_type, - const unsigned char *image); - static GLenum get_numeric_type(qpGeom::NumericType numeric_type); GLenum get_texture_target(Texture::TextureType texture_type) const; GLenum get_texture_wrap_mode(Texture::WrapMode wm); @@ -269,6 +257,15 @@ protected: void do_auto_rescale_normal(); void do_issue_texture(); + void specify_texture(Texture *tex); + void apply_texture(TextureContext *tc); + bool upload_texture(CLP(TextureContext) *gtc); + bool upload_texture_image(CLP(TextureContext) *gtc, bool uses_mipmaps, + GLenum target, GLint internal_format, + int width, int height, int depth, + GLint external_format, GLenum component_type, + const unsigned char *image); + void do_point_size(); #ifndef NDEBUG diff --git a/panda/src/glstuff/glTextureContext_src.I b/panda/src/glstuff/glTextureContext_src.I index 485d39411b..73096c9259 100644 --- a/panda/src/glstuff/glTextureContext_src.I +++ b/panda/src/glstuff/glTextureContext_src.I @@ -27,7 +27,6 @@ CLP(TextureContext)(Texture *tex) : TextureContext(tex) { _index = 0; - _priority = 0.5; // For keeping resident in texture memory _already_applied = false; } diff --git a/panda/src/glstuff/glTextureContext_src.h b/panda/src/glstuff/glTextureContext_src.h index c403e0a236..e4e948fff7 100644 --- a/panda/src/glstuff/glTextureContext_src.h +++ b/panda/src/glstuff/glTextureContext_src.h @@ -30,9 +30,6 @@ public: // This is the GL "name" of the texture object. GLuint _index; - // This is a GL texture priority. - GLfloat _priority; - // These are the parameters that we specified with the last // glTexImage2D() call. If none of these have changed, we can // reload the texture image with a glTexSubImage2D(). diff --git a/panda/src/gobj/texture.I b/panda/src/gobj/texture.I index e5688b38aa..b97813c00d 100644 --- a/panda/src/gobj/texture.I +++ b/panda/src/gobj/texture.I @@ -105,7 +105,7 @@ setup_3d_texture(int x_size, int y_size, int z_size, //////////////////////////////////////////////////////////////////// INLINE void Texture:: setup_cube_map() { - setup_cube_map(0, 1, T_unsigned_byte, F_rgb); + setup_cube_map(0, T_unsigned_byte, F_rgb); } //////////////////////////////////////////////////////////////////// @@ -114,12 +114,16 @@ setup_cube_map() { // Description: Sets the texture as an empty cube map texture with // the specified dimensions and properties. Follow up // with set_ram_image() or modify_ram_image() to fill -// the image data. +// the image data. +// +// Note that a cube map should always consist of six +// square images, so x_size and y_size will be the same, +// and z_size is always 6. //////////////////////////////////////////////////////////////////// INLINE void Texture:: -setup_cube_map(int x_size, int y_size, ComponentType component_type, +setup_cube_map(int size, ComponentType component_type, Format format) { - setup_texture(TT_cube_map, x_size, y_size, 6, component_type, format); + setup_texture(TT_cube_map, size, size, 6, component_type, format); } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gobj/texture.cxx b/panda/src/gobj/texture.cxx index 756ae30983..3e0859e74f 100644 --- a/panda/src/gobj/texture.cxx +++ b/panda/src/gobj/texture.cxx @@ -92,13 +92,17 @@ void Texture:: setup_texture(Texture::TextureType texture_type, int x_size, int y_size, int z_size, Texture::ComponentType component_type, Texture::Format format) { +#ifndef NDEBUG + if (texture_type == TT_cube_map) { + // Cube maps must always consist of six square images. + nassertv(x_size == y_size && z_size == 6); + } +#endif + _texture_type = texture_type; _x_size = x_size; _y_size = y_size; _z_size = z_size; - if (_texture_type == TT_cube_map) { - _z_size = 6; - } set_component_type(component_type); set_format(format); @@ -386,10 +390,9 @@ write_pages(const Filename &fullpath_template) { // multiple times, one for each page (z value). Cube // maps have exactly 6 pages, while 3-d textures can // have any number and can dynamically grow as each page -// is loaded. For the first page loaded (or when -// reloading z == 0), this also sets the texture -// parameters; for subsequent pages, the texture -// parameters must match those which were loaded +// is loaded. For the first page loaded, this also sets +// the texture parameters; for subsequent pages, the +// texture parameters must match those which were loaded // previously. // // This also implicitly sets keep_ram_image to false if @@ -451,13 +454,17 @@ load(const PNMImage &pnmimage, int z) { // Eh? nassertr(false, false); _format = F_rgb; - }; + } } - if (!_loaded_from_disk || z == 0) { + if (!_loaded_from_disk) { +#ifndef NDEBUG if (_texture_type == TT_1d_texture) { nassertr(pnmimage.get_y_size() == 1, false); + } else if (_texture_type == TT_cube_map) { + nassertr(pnmimage.get_x_size() == pnmimage.get_y_size(), false); } +#endif _x_size = pnmimage.get_x_size(); _y_size = pnmimage.get_y_size(); _num_components = num_components; diff --git a/panda/src/gobj/texture.h b/panda/src/gobj/texture.h index baf2174943..11e985e1f4 100644 --- a/panda/src/gobj/texture.h +++ b/panda/src/gobj/texture.h @@ -147,7 +147,7 @@ PUBLISHED: INLINE void setup_3d_texture(int x_size, int y_size, int z_size, ComponentType component_type, Format format); INLINE void setup_cube_map(); - INLINE void setup_cube_map(int x_size, int y_size, + INLINE void setup_cube_map(int size, ComponentType component_type, Format format); bool read(const Filename &fullpath, int z = 0, diff --git a/panda/src/gobj/textureContext.I b/panda/src/gobj/textureContext.I index a347bce1cb..9d6eafd91f 100644 --- a/panda/src/gobj/textureContext.I +++ b/panda/src/gobj/textureContext.I @@ -26,7 +26,7 @@ INLINE TextureContext:: TextureContext(Texture *tex) : _texture(tex) { - _dirty_flags = 0; + _dirty_flags = ~0; } //////////////////////////////////////////////////////////////////// diff --git a/panda/src/gsgbase/graphicsStateGuardianBase.h b/panda/src/gsgbase/graphicsStateGuardianBase.h index 9e1f4428e4..c16bcfd0c3 100644 --- a/panda/src/gsgbase/graphicsStateGuardianBase.h +++ b/panda/src/gsgbase/graphicsStateGuardianBase.h @@ -76,7 +76,6 @@ class RenderModeAttrib; class AntialiasAttrib; class RescaleNormalAttrib; class ColorBlendAttrib; -class TextureApplyAttrib; class ColorWriteAttrib; class AlphaTestAttrib; class DepthTestAttrib; @@ -135,7 +134,6 @@ public: virtual PreparedGraphicsObjects *get_prepared_objects()=0; virtual TextureContext *prepare_texture(Texture *tex)=0; - virtual void apply_texture(TextureContext *tc, int index=0)=0; virtual void release_texture(TextureContext *tc)=0; virtual GeomContext *prepare_geom(Geom *geom)=0; @@ -222,7 +220,6 @@ public: virtual void issue_render_mode(const RenderModeAttrib *) { } virtual void issue_antialias(const AntialiasAttrib *) { } virtual void issue_rescale_normal(const RescaleNormalAttrib *) { } - virtual void issue_texture_apply(const TextureApplyAttrib *) { } virtual void issue_color_write(const ColorWriteAttrib *) { } virtual void issue_depth_test(const DepthTestAttrib *) { } virtual void issue_depth_write(const DepthWriteAttrib *) { } diff --git a/panda/src/pgraph/Sources.pp b/panda/src/pgraph/Sources.pp index 059cf5c535..45f7d88b27 100644 --- a/panda/src/pgraph/Sources.pp +++ b/panda/src/pgraph/Sources.pp @@ -94,7 +94,6 @@ switchNode.I switchNode.h \ texMatrixAttrib.I texMatrixAttrib.h \ texProjectorEffect.I texProjectorEffect.h \ - textureApplyAttrib.I textureApplyAttrib.h \ textureAttrib.I textureAttrib.h \ texGenAttrib.I texGenAttrib.h \ textureCollection.I textureCollection.h \ @@ -192,7 +191,6 @@ switchNode.cxx \ texMatrixAttrib.cxx \ texProjectorEffect.cxx \ - textureApplyAttrib.cxx \ textureAttrib.cxx \ texGenAttrib.cxx \ textureCollection.cxx \ @@ -286,7 +284,6 @@ switchNode.I switchNode.h \ texMatrixAttrib.I texMatrixAttrib.h \ texProjectorEffect.I texProjectorEffect.h \ - textureApplyAttrib.I textureApplyAttrib.h \ textureAttrib.I textureAttrib.h \ texGenAttrib.I texGenAttrib.h \ textureCollection.I textureCollection.h \ diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index 257ab96941..8595c07010 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -85,7 +85,6 @@ #include "switchNode.h" #include "texMatrixAttrib.h" #include "texProjectorEffect.h" -#include "textureApplyAttrib.h" #include "textureAttrib.h" #include "texGenAttrib.h" #include "transformState.h" @@ -324,7 +323,6 @@ init_libpgraph() { SwitchNode::init_type(); TexMatrixAttrib::init_type(); TexProjectorEffect::init_type(); - TextureApplyAttrib::init_type(); TextureAttrib::init_type(); TexGenAttrib::init_type(); TransformState::init_type(); @@ -380,7 +378,6 @@ init_libpgraph() { SwitchNode::register_with_read_factory(); TexMatrixAttrib::register_with_read_factory(); TexProjectorEffect::register_with_read_factory(); - TextureApplyAttrib::register_with_read_factory(); TextureAttrib::register_with_read_factory(); TexGenAttrib::register_with_read_factory(); TransformState::register_with_read_factory(); diff --git a/panda/src/pgraph/lensNode.I b/panda/src/pgraph/lensNode.I index c64938c4ff..7d5c076fbe 100644 --- a/panda/src/pgraph/lensNode.I +++ b/panda/src/pgraph/lensNode.I @@ -18,8 +18,8 @@ //////////////////////////////////////////////////////////////////// -// Function: copy_lens -// Access: Public +// Function: LensNode::copy_lens +// Access: Published // Description: Sets up the LensNode using a copy of the // indicated Lens. If the original Lens is // changed or destroyed, this LensNode is not @@ -28,11 +28,14 @@ INLINE void LensNode:: copy_lens(const Lens &lens) { _lens = lens.make_copy(); + if (_shown_frustum != (PandaNode *)NULL) { + show_frustum(); + } } //////////////////////////////////////////////////////////////////// -// Function: set_lens -// Access: Public +// Function: LensNode::set_lens +// Access: Published // Description: Sets up the LensNode using this particular Lens // pointer. If the lens is subsequently modified, the // LensNode properties immediately reflect the change. @@ -40,11 +43,14 @@ copy_lens(const Lens &lens) { INLINE void LensNode:: set_lens(Lens *lens) { _lens = lens; + if (_shown_frustum != (PandaNode *)NULL) { + show_frustum(); + } } //////////////////////////////////////////////////////////////////// -// Function: get_lens -// Access: Public +// Function: LensNode::get_lens +// Access: Published // Description: Returns a pointer to the particular Lens // associated with this LensNode, or NULL if there is // not yet a Lens associated. diff --git a/panda/src/pgraph/lensNode.cxx b/panda/src/pgraph/lensNode.cxx index 810ba55064..af6d5e54bd 100644 --- a/panda/src/pgraph/lensNode.cxx +++ b/panda/src/pgraph/lensNode.cxx @@ -22,12 +22,13 @@ #include "bamReader.h" #include "datagram.h" #include "datagramIterator.h" +#include "geomNode.h" TypeHandle LensNode::_type_handle; //////////////////////////////////////////////////////////////////// // Function: LensNode::Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// LensNode:: @@ -50,7 +51,7 @@ LensNode(const LensNode ©) : //////////////////////////////////////////////////////////////////// // Function: LensNode::xform -// Access: Public, Virtual +// Access: Published, Virtual // Description: Transforms the contents of this PandaNode by the // indicated matrix, if it means anything to do so. For // most kinds of PandaNodes, this does nothing. @@ -63,7 +64,7 @@ xform(const LMatrix4f &mat) { //////////////////////////////////////////////////////////////////// // Function: LensNode::make_copy -// Access: Public, Virtual +// Access: Published, Virtual // Description: Returns a newly-allocated Node that is a shallow copy // of this one. It will be a different Node pointer, // but its internal data may or may not be shared with @@ -76,7 +77,7 @@ make_copy() const { //////////////////////////////////////////////////////////////////// // Function: LensNode::is_in_view -// Access: Public +// Access: Published // Description: Returns true if the given point is within the bounds // of the lens of the LensNode (i.e. if the camera can // see the point). @@ -92,6 +93,41 @@ is_in_view(const LPoint3f &pos) { return (ret != 0); } +//////////////////////////////////////////////////////////////////// +// Function: LensNode::show_frustum +// Access: Published +// Description: Enables the drawing of the lens's frustum to aid in +// visualization. This actually creates a GeomNode +// which is parented to the LensNode. +//////////////////////////////////////////////////////////////////// +void LensNode:: +show_frustum() { + if (_shown_frustum != (PandaNode *)NULL) { + hide_frustum(); + } + PT(GeomNode) geom_node = new GeomNode("frustum"); + _shown_frustum = geom_node; + add_child(_shown_frustum); + + if (_lens != (Lens *)NULL) { + geom_node->add_geom(_lens->make_geometry()); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: LensNode::hide_frustum +// Access: Published +// Description: Disables the drawing of the lens's frustum to aid in +// visualization. +//////////////////////////////////////////////////////////////////// +void LensNode:: +hide_frustum() { + if (_shown_frustum != (PandaNode *)NULL) { + remove_child(_shown_frustum); + _shown_frustum = (PandaNode *)NULL; + } +} + //////////////////////////////////////////////////////////////////// // Function: LensNode::output // Access: Public, Virtual diff --git a/panda/src/pgraph/lensNode.h b/panda/src/pgraph/lensNode.h index 38740cd862..47319f0cf6 100644 --- a/panda/src/pgraph/lensNode.h +++ b/panda/src/pgraph/lensNode.h @@ -52,8 +52,12 @@ PUBLISHED: bool is_in_view(const LPoint3f &pos); + void show_frustum(); + void hide_frustum(); + protected: PT(Lens) _lens; + PT(PandaNode) _shown_frustum; public: static void register_with_read_factory(); diff --git a/panda/src/pgraph/pgraph_composite4.cxx b/panda/src/pgraph/pgraph_composite4.cxx index e05f8bdc93..56353e8144 100644 --- a/panda/src/pgraph/pgraph_composite4.cxx +++ b/panda/src/pgraph/pgraph_composite4.cxx @@ -14,7 +14,6 @@ #include "switchNode.cxx" #include "texMatrixAttrib.cxx" #include "texProjectorEffect.cxx" -#include "textureApplyAttrib.cxx" #include "textureAttrib.cxx" #include "texGenAttrib.cxx" #include "textureCollection.cxx" diff --git a/panda/src/pgraph/spotlight.cxx b/panda/src/pgraph/spotlight.cxx index e85f705de6..1fb892e376 100644 --- a/panda/src/pgraph/spotlight.cxx +++ b/panda/src/pgraph/spotlight.cxx @@ -141,6 +141,54 @@ write(ostream &out, int indent_level) const { } } +//////////////////////////////////////////////////////////////////// +// Function: Spotlight::make_spot +// Access: Published, Static +// Description: Returns a newly-generated Texture that renders a +// circular spot image as might be cast from the +// spotlight. This may be projected onto target +// geometry (for instance, via +// NodePath::project_texture()) instead of actually +// enabling the light itself, as a cheesy way to make a +// high-resolution spot appear on the geometry. +// +// pixel_width specifies the height and width of the new +// texture in pixels, full_radius is a value in the +// range 0..1 that indicates the relative size of the +// fully bright center spot, and fg and bg are the +// colors of the interior and exterior of the spot, +// respectively. +//////////////////////////////////////////////////////////////////// +PT(Texture) Spotlight:: +make_spot(int pixel_width, float full_radius, Colorf &fg, Colorf &bg) { + int num_channels; + if (fg[0] == fg[1] && fg[1] == fg[2] && + bg[0] == bg[1] && bg[1] == bg[2]) { + // grayscale + num_channels = 1; + } else { + // color + num_channels = 3; + } + if (fg[3] != 1.0f || bg[3] != 1.0f) { + // with alpha. + ++num_channels; + } + PNMImage image(pixel_width, pixel_width, num_channels); + image.render_spot(LCAST(double, fg), LCAST(double, bg), full_radius, 1.0); + + PT(Texture) tex = new Texture("spot"); + tex->load(image); + tex->set_border_color(bg); + tex->set_wrap_u(Texture::WM_border_color); + tex->set_wrap_v(Texture::WM_border_color); + + tex->set_minfilter(Texture::FT_linear); + tex->set_magfilter(Texture::FT_linear); + + return tex; +} + //////////////////////////////////////////////////////////////////// // Function: Spotlight::bind // Access: Public, Virtual @@ -151,80 +199,6 @@ bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id) { gsg->bind_light(this, light, light_id); } -//////////////////////////////////////////////////////////////////// -// Function: Spotlight::make_image -// Access: Public -// Description: Generates an image into the indicated texture of a -// circle with a soft edge that corresponds to the -// falloff of the spotlight. This is intended to be -// used to implement projected texture spotlights; the -// image can be applied to geometry with UV's computed -// appropriate to simulate the texture's region of -// influence. -// -// Returns true if the image is successfully generated, -// false otherwise. -//////////////////////////////////////////////////////////////////// -bool Spotlight:: -make_image(Texture *texture, float radius) { - if (texture == NULL) { - pgraph_cat.error() - << "Spotlight::make_image() - NULL texture" << endl; - return false; - } - int size = min(texture->get_x_size(), texture->get_y_size()); - if (size == 0) { - size = 64; - } - - PNMImage image(size, size, 1); - - const Colorf &c4 = get_color(); - const RGBColord color(c4[0], c4[1], c4[2]); - - int half_width = (size - 2) / 2; - float dXY = 1 / (float)half_width; - float Y = dXY + dXY; - float X, YY, dist_from_center, intensity; - int tx, ty, tx2, ty2; - - for (int y = 0; y < half_width; y++, Y += dXY) { - X = dXY * y + dXY; - YY = Y * Y; - ty = y + half_width; - - for (int x = y; x < half_width; x++, X += dXY) { - dist_from_center = (float)sqrt(X * X + YY); - float D = dist_from_center; - if (D <= radius) - intensity = 1.0f; - else if (D < 1.0f) - intensity = pow(cos((D-radius) / - (1.0f-radius) * (MathNumbers::pi_f*0.5f)), get_exponent()); - else - intensity = 0; - - tx = x + half_width; - - image.set_xel(tx, ty, color * intensity); - image.set_xel(tx, size - ty - 1, color * intensity); - image.set_xel(size - tx - 1, ty, color * intensity); - image.set_xel(size - tx - 1, size - ty - 1, color * intensity); - - tx2 = ty; ty2 = tx; - - image.set_xel(tx2, ty2, color * intensity); - image.set_xel(tx2, size - ty2 - 1, color * intensity); - image.set_xel(size - tx2 - 1, ty2, color * intensity); - image.set_xel(size - tx2 - 1, size - ty2 - 1, color * intensity); - } - } - - texture->load(image); - - return true; -} - //////////////////////////////////////////////////////////////////// // Function: Spotlight::fill_viz_geom // Access: Protected, Virtual diff --git a/panda/src/pgraph/spotlight.h b/panda/src/pgraph/spotlight.h index 577bea8e18..65695242b6 100644 --- a/panda/src/pgraph/spotlight.h +++ b/panda/src/pgraph/spotlight.h @@ -60,13 +60,14 @@ PUBLISHED: INLINE const LVecBase3f &get_attenuation() const; INLINE void set_attenuation(const LVecBase3f &attenuation); + + static PT(Texture) make_spot(int pixel_width, float full_radius, + Colorf &fg, Colorf &bg); public: virtual void bind(GraphicsStateGuardianBase *gsg, const NodePath &light, int light_id); - bool make_image(Texture *texture, float radius); - protected: virtual void fill_viz_geom(GeomNode *viz_geom); diff --git a/panda/src/pgraph/textureApplyAttrib.I b/panda/src/pgraph/textureApplyAttrib.I deleted file mode 100644 index 181d28155c..0000000000 --- a/panda/src/pgraph/textureApplyAttrib.I +++ /dev/null @@ -1,40 +0,0 @@ -// Filename: textureApplyAttrib.I -// Created by: drose (04Mar02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::Constructor -// Access: Private -// Description: Use TextureApplyAttrib::make() to construct a new -// TextureApplyAttrib object. -//////////////////////////////////////////////////////////////////// -INLINE TextureApplyAttrib:: -TextureApplyAttrib(TextureApplyAttrib::Mode mode) : - _mode(mode) -{ -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::get_mode -// Access: Published -// Description: Returns the culling mode. -//////////////////////////////////////////////////////////////////// -INLINE TextureApplyAttrib::Mode TextureApplyAttrib:: -get_mode() const { - return _mode; -} diff --git a/panda/src/pgraph/textureApplyAttrib.cxx b/panda/src/pgraph/textureApplyAttrib.cxx deleted file mode 100644 index 537c03584b..0000000000 --- a/panda/src/pgraph/textureApplyAttrib.cxx +++ /dev/null @@ -1,179 +0,0 @@ -// Filename: textureApplyAttrib.cxx -// Created by: drose (04Mar02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#include "textureApplyAttrib.h" -#include "graphicsStateGuardianBase.h" -#include "dcast.h" -#include "bamReader.h" -#include "bamWriter.h" -#include "datagram.h" -#include "datagramIterator.h" - -TypeHandle TextureApplyAttrib::_type_handle; - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::make -// Access: Published, Static -// Description: Constructs a new TextureApplyAttrib object. -//////////////////////////////////////////////////////////////////// -CPT(RenderAttrib) TextureApplyAttrib:: -make(TextureApplyAttrib::Mode mode) { - TextureApplyAttrib *attrib = new TextureApplyAttrib(mode); - return return_new(attrib); -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::issue -// Access: Public, Virtual -// Description: Calls the appropriate method on the indicated GSG -// to issue the graphics commands appropriate to the -// given attribute. This is normally called -// (indirectly) only from -// GraphicsStateGuardian::set_state() or modify_state(). -//////////////////////////////////////////////////////////////////// -void TextureApplyAttrib:: -issue(GraphicsStateGuardianBase *gsg) const { - gsg->issue_texture_apply(this); -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::output -// Access: Public, Virtual -// Description: -//////////////////////////////////////////////////////////////////// -void TextureApplyAttrib:: -output(ostream &out) const { - out << get_type() << ":"; - switch (get_mode()) { - case M_modulate: - out << "modulate"; - break; - - case M_decal: - out << "decal"; - break; - - case M_blend: - out << "blend"; - break; - - case M_replace: - out << "replace"; - break; - - case M_add: - out << "add"; - break; - } -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::compare_to_impl -// Access: Protected, Virtual -// Description: Intended to be overridden by derived TextureApplyAttrib -// types to return a unique number indicating whether -// this TextureApplyAttrib is equivalent to the other one. -// -// This should return 0 if the two TextureApplyAttrib objects -// are equivalent, a number less than zero if this one -// should be sorted before the other one, and a number -// greater than zero otherwise. -// -// This will only be called with two TextureApplyAttrib -// objects whose get_type() functions return the same. -//////////////////////////////////////////////////////////////////// -int TextureApplyAttrib:: -compare_to_impl(const RenderAttrib *other) const { - const TextureApplyAttrib *ta; - DCAST_INTO_R(ta, other, 0); - return (int)_mode - (int)ta->_mode; -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::make_default_impl -// Access: Protected, Virtual -// Description: Intended to be overridden by derived TextureApplyAttrib -// types to specify what the default property for a -// TextureApplyAttrib of this type should be. -// -// This should return a newly-allocated TextureApplyAttrib of -// the same type that corresponds to whatever the -// standard default for this kind of TextureApplyAttrib is. -//////////////////////////////////////////////////////////////////// -RenderAttrib *TextureApplyAttrib:: -make_default_impl() const { - return new TextureApplyAttrib; -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::register_with_read_factory -// Access: Public, Static -// Description: Tells the BamReader how to create objects of type -// TextureApplyAttrib. -//////////////////////////////////////////////////////////////////// -void TextureApplyAttrib:: -register_with_read_factory() { - BamReader::get_factory()->register_factory(get_class_type(), make_from_bam); -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::write_datagram -// Access: Public, Virtual -// Description: Writes the contents of this object to the datagram -// for shipping out to a Bam file. -//////////////////////////////////////////////////////////////////// -void TextureApplyAttrib:: -write_datagram(BamWriter *manager, Datagram &dg) { - RenderAttrib::write_datagram(manager, dg); - - dg.add_int8(_mode); -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::make_from_bam -// Access: Protected, Static -// Description: This function is called by the BamReader's factory -// when a new object of type TextureApplyAttrib is encountered -// in the Bam file. It should create the TextureApplyAttrib -// and extract its information from the file. -//////////////////////////////////////////////////////////////////// -TypedWritable *TextureApplyAttrib:: -make_from_bam(const FactoryParams ¶ms) { - TextureApplyAttrib *attrib = new TextureApplyAttrib; - DatagramIterator scan; - BamReader *manager; - - parse_params(params, scan, manager); - attrib->fillin(scan, manager); - - return attrib; -} - -//////////////////////////////////////////////////////////////////// -// Function: TextureApplyAttrib::fillin -// Access: Protected -// Description: This internal function is called by make_from_bam to -// read in all of the relevant data from the BamFile for -// the new TextureApplyAttrib. -//////////////////////////////////////////////////////////////////// -void TextureApplyAttrib:: -fillin(DatagramIterator &scan, BamReader *manager) { - RenderAttrib::fillin(scan, manager); - - _mode = (Mode)scan.get_int8(); -} diff --git a/panda/src/pgraph/textureApplyAttrib.h b/panda/src/pgraph/textureApplyAttrib.h deleted file mode 100644 index 31e4a38435..0000000000 --- a/panda/src/pgraph/textureApplyAttrib.h +++ /dev/null @@ -1,95 +0,0 @@ -// Filename: textureApplyAttrib.h -// Created by: drose (04Mar02) -// -//////////////////////////////////////////////////////////////////// -// -// PANDA 3D SOFTWARE -// Copyright (c) 2001 - 2004, Disney Enterprises, Inc. All rights reserved -// -// All use of this software is subject to the terms of the Panda 3d -// Software license. You should have received a copy of this license -// along with this source code; you will also find a current copy of -// the license at http://etc.cmu.edu/panda3d/docs/license/ . -// -// To contact the maintainers of this program write to -// panda3d-general@lists.sourceforge.net . -// -//////////////////////////////////////////////////////////////////// - -#ifndef TEXTUREAPPLYATTRIB_H -#define TEXTUREAPPLYATTRIB_H - -#include "pandabase.h" - -#include "renderAttrib.h" - -class FactoryParams; - -//////////////////////////////////////////////////////////////////// -// Class : TextureApplyAttrib -// Description : Specifies how textures are applied; specifically, how -// texture color modifies geometry color. -// -// This class is now deprecated; it has been replaced -// with the TextureStage class to support -// multitexturing. -//////////////////////////////////////////////////////////////////// -class EXPCL_PANDA TextureApplyAttrib : public RenderAttrib { -PUBLISHED: - enum Mode { - M_modulate, - M_decal, - M_blend, - M_replace, - M_add - }; - -private: - INLINE TextureApplyAttrib(Mode mode = M_modulate); - -PUBLISHED: - static CPT(RenderAttrib) make(Mode mode); - - INLINE Mode get_mode() const; - -public: - virtual void issue(GraphicsStateGuardianBase *gsg) const; - virtual void output(ostream &out) const; - -protected: - virtual int compare_to_impl(const RenderAttrib *other) const; - virtual RenderAttrib *make_default_impl() const; - -private: - Mode _mode; - -public: - static void register_with_read_factory(); - virtual void write_datagram(BamWriter *manager, Datagram &dg); - -protected: - static TypedWritable *make_from_bam(const FactoryParams ¶ms); - void fillin(DatagramIterator &scan, BamReader *manager); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - RenderAttrib::init_type(); - register_type(_type_handle, "TextureApplyAttrib", - RenderAttrib::get_class_type()); - } - virtual TypeHandle get_type() const { - return get_class_type(); - } - virtual TypeHandle force_init_type() {init_type(); return get_class_type();} - -private: - static TypeHandle _type_handle; -}; - -#include "textureApplyAttrib.I" - -#endif - diff --git a/panda/src/pnmimage/pnmImage.I b/panda/src/pnmimage/pnmImage.I index 0ca3920a03..6002a743d3 100644 --- a/panda/src/pnmimage/pnmImage.I +++ b/panda/src/pnmimage/pnmImage.I @@ -18,7 +18,7 @@ //////////////////////////////////////////////////////////////////// // Function: PNMImage::Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PNMImage:: @@ -29,7 +29,7 @@ PNMImage() { //////////////////////////////////////////////////////////////////// // Function: PNMImage::Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PNMImage:: @@ -42,7 +42,7 @@ PNMImage(const Filename &filename, PNMFileType *type) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PNMImage:: @@ -56,7 +56,7 @@ PNMImage(int x_size, int y_size, int num_channels, xelval maxval, //////////////////////////////////////////////////////////////////// // Function: PNMImage::Copy Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PNMImage:: @@ -71,7 +71,7 @@ PNMImage(const PNMImage ©) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::Copy Assigment Operator -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE void PNMImage:: @@ -81,7 +81,7 @@ operator = (const PNMImage ©) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::Destructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PNMImage:: @@ -92,7 +92,7 @@ INLINE PNMImage:: //////////////////////////////////////////////////////////////////// // Function: PNMImage::clamp_val -// Access: Public +// Access: Published // Description: A handy function to clamp values to // [0..get_maxval()]. //////////////////////////////////////////////////////////////////// @@ -103,7 +103,7 @@ clamp_val(int input_value) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::to_val -// Access: Public +// Access: Published // Description: A handy function to scale values from [0..1] to // [0..get_maxval()]. //////////////////////////////////////////////////////////////////// @@ -114,7 +114,7 @@ to_val(double input_value) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::from_val -// Access: Public +// Access: Published // Description: A handy function to scale values from // [0..get_maxval()] to [0..1]. //////////////////////////////////////////////////////////////////// @@ -125,7 +125,7 @@ from_val(xelval input_value) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::fill -// Access: Public +// Access: Published // Description: Sets the entire image (except the alpha channel) to // the given color. //////////////////////////////////////////////////////////////////// @@ -138,7 +138,7 @@ fill(double red, double green, double blue) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::fill -// Access: Public +// Access: Published // Description: Sets the entire image (except the alpha channel) to // the given grayscale level. //////////////////////////////////////////////////////////////////// @@ -149,7 +149,7 @@ fill(double gray) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::fill_val -// Access: Public +// Access: Published // Description: Sets the entire image (except the alpha channel) to // the given grayscale level. //////////////////////////////////////////////////////////////////// @@ -160,7 +160,7 @@ fill_val(xelval gray) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::alpha_fill -// Access: Public +// Access: Published // Description: Sets the entire alpha channel to the given level. //////////////////////////////////////////////////////////////////// INLINE void PNMImage:: @@ -170,7 +170,7 @@ alpha_fill(double alpha) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::is_valid -// Access: Public +// Access: Published // Description: Returns true if the image has been read in or // correctly initialized with a height and width. If // this returns false, virtually all member functions @@ -183,7 +183,7 @@ is_valid() const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_num_channels -// Access: Public +// Access: Published // Description: Changes the number of channels associated with the // image. The new number of channels must be an integer // in the range 1 through 4, inclusive. This will @@ -198,7 +198,7 @@ set_num_channels(int num_channels) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::add_alpha -// Access: Public +// Access: Published // Description: Adds an alpha channel to the image, if it does not // already have one. The alpha channel is initialized // to zeros. @@ -210,7 +210,7 @@ add_alpha() { //////////////////////////////////////////////////////////////////// // Function: PNMImage::remove_alpha -// Access: Public +// Access: Published // Description: Removes the image's alpha channel, if it exists. //////////////////////////////////////////////////////////////////// INLINE void PNMImage:: @@ -220,7 +220,7 @@ remove_alpha() { //////////////////////////////////////////////////////////////////// // Function: PNMImage::make_grayscale -// Access: Public +// Access: Published // Description: Converts the image from RGB to grayscale. Any alpha // channel, if present, is left undisturbed. //////////////////////////////////////////////////////////////////// @@ -231,7 +231,7 @@ make_grayscale() { //////////////////////////////////////////////////////////////////// // Function: PNMImage::make_rgb -// Access: Public +// Access: Published // Description: Converts the image from grayscale to RGB. Any alpha // channel, if present, is left undisturbed. //////////////////////////////////////////////////////////////////// @@ -242,7 +242,7 @@ make_rgb() { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_xel_val -// Access: Public +// Access: Published // Description: Returns the RGB color at the indicated pixel. Each // component is in the range 0..maxval. //////////////////////////////////////////////////////////////////// @@ -253,7 +253,7 @@ get_xel_val(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_xel_val -// Access: Public +// Access: Published // Description: Changes the RGB color at the indicated pixel. Each // component is in the range 0..maxval. //////////////////////////////////////////////////////////////////// @@ -264,7 +264,7 @@ set_xel_val(int x, int y, const xel &value) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_xel_val -// Access: Public +// Access: Published // Description: Changes the RGB color at the indicated pixel. Each // component is in the range 0..maxval. //////////////////////////////////////////////////////////////////// @@ -275,7 +275,7 @@ set_xel_val(int x, int y, xelval r, xelval g, xelval b) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_xel_val -// Access: Public +// Access: Published // Description: Changes all three color components at the indicated // pixel to the same value. The value is in the range // 0..maxval. @@ -287,7 +287,7 @@ set_xel_val(int x, int y, xelval gray) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_red_val -// Access: Public +// Access: Published // Description: Returns the red component color at the indicated // pixel. The value returned is in the range 0..maxval. //////////////////////////////////////////////////////////////////// @@ -298,7 +298,7 @@ get_red_val(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_green_val -// Access: Public +// Access: Published // Description: Returns the green component color at the indicated // pixel. The value returned is in the range 0..maxval. //////////////////////////////////////////////////////////////////// @@ -309,7 +309,7 @@ get_green_val(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_blue_val -// Access: Public +// Access: Published // Description: Returns the blue component color at the indicated // pixel. The value returned is in the range 0..maxval. //////////////////////////////////////////////////////////////////// @@ -320,7 +320,7 @@ get_blue_val(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_gray_val -// Access: Public +// Access: Published // Description: Returns the gray component color at the indicated // pixel. This only has a meaningful value for // grayscale images; for other image types, this returns @@ -335,7 +335,7 @@ get_gray_val(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_alpha_val -// Access: Public +// Access: Published // Description: Returns the alpha component color at the indicated // pixel. It is an error to call this unless // has_alpha() is true. The value returned is in the @@ -348,7 +348,7 @@ get_alpha_val(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_red_val -// Access: Public +// Access: Published // Description: Sets the red component color only at the indicated // pixel. The value given should be in the range // 0..maxval. @@ -360,7 +360,7 @@ set_red_val(int x, int y, xelval r) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_green_val -// Access: Public +// Access: Published // Description: Sets the green component color only at the indicated // pixel. The value given should be in the range // 0..maxval. @@ -372,7 +372,7 @@ set_green_val(int x, int y, xelval g) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_blue_val -// Access: Public +// Access: Published // Description: Sets the blue component color only at the indicated // pixel. The value given should be in the range // 0..maxval. @@ -384,7 +384,7 @@ set_blue_val(int x, int y, xelval b) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_gray_val -// Access: Public +// Access: Published // Description: Sets the gray component color at the indicated // pixel. This is only meaningful for grayscale images; // for other image types, this simply sets the blue @@ -401,7 +401,7 @@ set_gray_val(int x, int y, xelval gray) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_alpha_val -// Access: Public +// Access: Published // Description: Sets the alpha component color only at the indicated // pixel. It is an error to call this unless // has_alpha() is true. The value given should be in @@ -414,7 +414,7 @@ set_alpha_val(int x, int y, xelval a) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_xel -// Access: Public +// Access: Published // Description: Returns the RGB color at the indicated pixel. Each // component is a double in the range 0..1. //////////////////////////////////////////////////////////////////// @@ -427,7 +427,7 @@ get_xel(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_xel -// Access: Public +// Access: Published // Description: Changes the RGB color at the indicated pixel. Each // component is a double in the range 0..1. //////////////////////////////////////////////////////////////////// @@ -438,7 +438,7 @@ set_xel(int x, int y, const RGBColord &value) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_xel -// Access: Public +// Access: Published // Description: Changes the RGB color at the indicated pixel. Each // component is a double in the range 0..1. //////////////////////////////////////////////////////////////////// @@ -449,7 +449,7 @@ set_xel(int x, int y, double r, double g, double b) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_xel -// Access: Public +// Access: Published // Description: Changes all three color components at the indicated // pixel to the same value. The value is a double in // the range 0..1. @@ -459,9 +459,58 @@ set_xel(int x, int y, double gray) { set_xel_val(x, y, to_val(gray), to_val(gray), to_val(gray)); } +//////////////////////////////////////////////////////////////////// +// Function: PNMImage::get_xel_a +// Access: Published +// Description: Returns the RGBA color at the indicated pixel. Each +// component is a double in the range 0..1. +//////////////////////////////////////////////////////////////////// +INLINE Colord PNMImage:: +get_xel_a(int x, int y) const { + if (has_alpha()) { + return Colord(from_val(get_red_val(x, y)), + from_val(get_green_val(x, y)), + from_val(get_blue_val(x, y)), + from_val(get_alpha_val(x, y))); + } else { + return Colord(from_val(get_red_val(x, y)), + from_val(get_green_val(x, y)), + from_val(get_blue_val(x, y)), + 0.0); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PNMImage::set_xel_a +// Access: Published +// Description: Changes the RGBA color at the indicated pixel. Each +// component is a double in the range 0..1. +//////////////////////////////////////////////////////////////////// +INLINE void PNMImage:: +set_xel_a(int x, int y, const Colord &value) { + set_xel_val(x, y, to_val(value[0]), to_val(value[1]), to_val(value[2])); + if (has_alpha()) { + set_alpha_val(x, y, to_val(value[3])); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PNMImage::set_xel_a +// Access: Published +// Description: Changes the RGBA color at the indicated pixel. Each +// component is a double in the range 0..1. +//////////////////////////////////////////////////////////////////// +INLINE void PNMImage:: +set_xel_a(int x, int y, double r, double g, double b, double a) { + set_xel_val(x, y, to_val(r), to_val(g), to_val(b)); + if (has_alpha()) { + set_alpha_val(x, y, to_val(a)); + } +} + //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_red -// Access: Public +// Access: Published // Description: Returns the red component color at the indicated // pixel. The value returned is a double in the range // 0..1. @@ -473,7 +522,7 @@ get_red(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_green -// Access: Public +// Access: Published // Description: Returns the green component color at the indicated // pixel. The value returned is a double in the range // 0..1. @@ -485,7 +534,7 @@ get_green(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_blue -// Access: Public +// Access: Published // Description: Returns the blue component color at the indicated // pixel. The value returned is a double in the range // 0..1. @@ -497,7 +546,7 @@ get_blue(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_gray -// Access: Public +// Access: Published // Description: Returns the gray component color at the indicated // pixel. This only has a meaningful value for // grayscale images; for other image types, this returns @@ -512,7 +561,7 @@ get_gray(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_alpha -// Access: Public +// Access: Published // Description: Returns the alpha component color at the indicated // pixel. It is an error to call this unless // has_alpha() is true. The value returned is a double @@ -525,7 +574,7 @@ get_alpha(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_red -// Access: Public +// Access: Published // Description: Sets the red component color only at the indicated // pixel. The value given should be a double in the // range 0..1. @@ -537,7 +586,7 @@ set_red(int x, int y, double r) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_green -// Access: Public +// Access: Published // Description: Sets the green component color only at the indicated // pixel. The value given should be a double in the // range 0..1. @@ -549,7 +598,7 @@ set_green(int x, int y, double r) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_blue -// Access: Public +// Access: Published // Description: Sets the blue component color only at the indicated // pixel. The value given should be a double in the // range 0..1. @@ -561,7 +610,7 @@ set_blue(int x, int y, double r) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_gray -// Access: Public +// Access: Published // Description: Sets the gray component color at the indicated // pixel. This is only meaningful for grayscale images; // for other image types, this simply sets the blue @@ -578,7 +627,7 @@ set_gray(int x, int y, double r) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_alpha -// Access: Public +// Access: Published // Description: Sets the alpha component color only at the indicated // pixel. It is an error to call this unless // has_alpha() is true. The value given should be in @@ -591,7 +640,7 @@ set_alpha(int x, int y, double r) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_channel -// Access: Public +// Access: Published // Description: Returns the nth component color at the indicated // pixel. The channel index should be in the range // 0..(get_num_channels()-1). The channels are ordered B, @@ -607,7 +656,7 @@ get_channel(int x, int y, int channel) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_channel_val -// Access: Public +// Access: Published // Description: Sets the nth component color at the indicated // pixel. The channel index should be in the range // 0..(get_num_channels()-1). The channels are ordered B, @@ -623,7 +672,7 @@ set_channel(int x, int y, int channel, double value) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_bright -// Access: Public +// Access: Published // Description: Returns the linear brightness of the given xel, as a // double in the range 0..1. This flavor of // get_bright() returns the correct grayscale brightness @@ -636,7 +685,7 @@ get_bright(int x, int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_bright -// Access: Public +// Access: Published // Description: This flavor of get_bright() works correctly only for // color images. It returns a single brightness value // for the RGB color at the indicated pixel, based on @@ -651,7 +700,7 @@ get_bright(int x, int y, double rc, double gc, double bc) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_bright -// Access: Public +// Access: Published // Description: This flavor of get_bright() works correctly only for // four-channel images. It returns a single brightness // value for the RGBA color at the indicated pixel, @@ -667,7 +716,7 @@ get_bright(int x, int y, double rc, double gc, double bc, double ac) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::blend -// Access: Public +// Access: Published // Description: Smoothly blends the indicated pixel value in with // whatever was already in the image, based on the given // alpha value. An alpha of 1.0 is fully opaque and @@ -681,7 +730,7 @@ blend(int x, int y, const RGBColord &val, double alpha) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::Array Operator -// Access: Public +// Access: Published // Description: Allows the PNMImage to appear to be a 2-d array of // xels. //////////////////////////////////////////////////////////////////// @@ -692,7 +741,7 @@ operator [] (int y) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::Array Operator -// Access: Public +// Access: Published // Description: Allows the PNMImage to appear to be a 2-d array of // xels. //////////////////////////////////////////////////////////////////// @@ -703,7 +752,7 @@ operator [] (int y) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::box_filter -// Access: Public +// Access: Published // Description: This flavor of box_filter() will apply the filter // over the entire image without resizing or copying; // the effect is that of a blur operation. @@ -715,7 +764,7 @@ box_filter(double radius) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::gaussian_filter -// Access: Public +// Access: Published // Description: This flavor of gaussian_filter() will apply the filter // over the entire image without resizing or copying; // the effect is that of a blur operation. diff --git a/panda/src/pnmimage/pnmImage.cxx b/panda/src/pnmimage/pnmImage.cxx index 440f438e9e..2074702fba 100644 --- a/panda/src/pnmimage/pnmImage.cxx +++ b/panda/src/pnmimage/pnmImage.cxx @@ -23,7 +23,7 @@ //////////////////////////////////////////////////////////////////// // Function: PNMImage::clear -// Access: Public +// Access: Published // Description: Frees all memory allocated for the image, and clears // all its parameters (size, color, type, etc). //////////////////////////////////////////////////////////////////// @@ -46,7 +46,7 @@ clear() { //////////////////////////////////////////////////////////////////// // Function: PNMImage::clear -// Access: Public +// Access: Published // Description: This flavor of clear() reinitializes the image to an // empty (black) image with the given dimensions. //////////////////////////////////////////////////////////////////// @@ -75,7 +75,7 @@ clear(int x_size, int y_size, int num_channels, //////////////////////////////////////////////////////////////////// // Function: PNMImage::copy_from -// Access: Public +// Access: Published // Description: Makes this image become a copy of the other image. //////////////////////////////////////////////////////////////////// void PNMImage:: @@ -94,7 +94,7 @@ copy_from(const PNMImage ©) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::copy_header_from -// Access: Public +// Access: Published // Description: Copies just the header information into this image. // This will blow away any image data stored in the // image. The new image data will be allocated, but @@ -115,7 +115,7 @@ copy_header_from(const PNMImageHeader &header) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::fill_val -// Access: Public +// Access: Published // Description: Sets the entire image (except the alpha channel) to // the given color. //////////////////////////////////////////////////////////////////// @@ -132,7 +132,7 @@ fill_val(xelval red, xelval green, xelval blue) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::alpha_fill_val -// Access: Public +// Access: Published // Description: Sets the entire alpha channel to the given level. //////////////////////////////////////////////////////////////////// void PNMImage:: @@ -152,7 +152,7 @@ alpha_fill_val(xelval alpha) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::read -// Access: Public +// Access: Published // Description: Reads the indicated image filename. If type is // non-NULL, it is a suggestion for the type of file it // is. Returns true if successful, false on error. @@ -170,7 +170,7 @@ read(const Filename &filename, PNMFileType *type) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::read -// Access: Public +// Access: Published // Description: Reads the image data from the indicated stream. // // The filename is advisory only, and may be used @@ -194,7 +194,7 @@ read(istream &data, const string &filename, PNMFileType *type) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::read -// Access: Public +// Access: Published // Description: This flavor of read() uses an already-existing // PNMReader to read the image file. You can get a // reader via the PNMImageHeader::make_reader() methods. @@ -236,7 +236,7 @@ read(PNMReader *reader) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::write -// Access: Public +// Access: Published // Description: Writes the image to the indicated filename. If type // is non-NULL, it is a suggestion for the type of image // file to write. @@ -257,7 +257,7 @@ write(const Filename &filename, PNMFileType *type) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::write -// Access: Public +// Access: Published // Description: Writes the image to the indicated ostream. // // The filename is advisory only, and may be used @@ -283,7 +283,7 @@ write(ostream &data, const string &filename, PNMFileType *type) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::write -// Access: Public +// Access: Published // Description: This flavor of write() uses an already-existing // PNMWriter to write the image file. You can get a // writer via the PNMImageHeader::make_writer() methods. @@ -313,7 +313,7 @@ write(PNMWriter *writer) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_color_type -// Access: Public +// Access: Published // Description: Translates the image to or from grayscale, color, or // four-color mode. Grayscale images are converted to // full-color images with R, G, B set to the original @@ -364,7 +364,7 @@ set_color_type(PNMImage::ColorType color_type) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::make_grayscale -// Access: Public +// Access: Published // Description: Converts the image from RGB to grayscale. Any alpha // channel, if present, is left undisturbed. The // optional rc, gc, bc values represent the relative @@ -389,7 +389,7 @@ make_grayscale(double rc, double gc, double bc) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_maxval -// Access: Public +// Access: Published // Description: Rescales the image to the indicated maxval. //////////////////////////////////////////////////////////////////// void PNMImage:: @@ -429,7 +429,7 @@ set_maxval(xelval maxval) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::get_channel_val -// Access: Public +// Access: Published // Description: Returns the nth component color at the indicated // pixel. The channel index should be in the range // 0..(get_num_channels()-1). The channels are ordered B, @@ -464,7 +464,7 @@ get_channel_val(int x, int y, int channel) const { //////////////////////////////////////////////////////////////////// // Function: PNMImage::set_channel_val -// Access: Public +// Access: Published // Description: Sets the nth component color at the indicated // pixel. The channel index should be in the range // 0..(get_num_channels()-1). The channels are ordered B, @@ -503,7 +503,7 @@ set_channel_val(int x, int y, int channel, xelval value) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::blend -// Access: Public +// Access: Published // Description: Smoothly blends the indicated pixel value in with // whatever was already in the image, based on the given // alpha value. An alpha of 1.0 is fully opaque and @@ -546,7 +546,7 @@ blend(int x, int y, double r, double g, double b, double alpha) { //////////////////////////////////////////////////////////////////// // Function: PNMImage::copy_sub_image -// Access: Public +// Access: Published // Description: Copies a rectangular area of another image into a // rectangular area of this image. Both images must // already have been initialized. The upper-left corner @@ -598,7 +598,7 @@ copy_sub_image(const PNMImage ©, int xto, int yto, //////////////////////////////////////////////////////////////////// // Function: PNMImage::blend_sub_image -// Access: Public +// Access: Published // Description: Behaves like copy_sub_image(), except the alpha // channel of the copy is used to blend the copy into // the destination image, instead of overwriting pixels @@ -646,10 +646,73 @@ blend_sub_image(const PNMImage ©, int xto, int yto, } } +//////////////////////////////////////////////////////////////////// +// Function: PNMImage::render_spot +// Access: Published +// Description: Renders a solid-color circle, with a fuzzy edge, into +// the center of the PNMImage. If the PNMImage is +// non-square, this actually renders an ellipse. +// +// The min_radius and max_radius are in the scale 0..1, +// where 1.0 means the full width of the image. If +// min_radius == max_radius, there is no fuzzy edge; +// otherwise, the pixels between min_radius and +// max_radius are smoothly blended between fg and bg +// colors. +//////////////////////////////////////////////////////////////////// +void PNMImage:: +render_spot(const Colord &fg, const Colord &bg, + double min_radius, double max_radius) { + double x_scale = 2.0 / _x_size; + double y_scale = 2.0 / _y_size; + + // If the width is even, x_center1 == x_center0. If the width is + // odd, x_center1 == x_center0 + 1. + int x_center0 = _x_size / 2; + int y_center0 = _y_size / 2; + int x_center1 = (_x_size + 1) / 2; + int y_center1 = (_y_size + 1) / 2; + + double min_r2 = min_radius * min_radius; + double max_r2 = max_radius * max_radius; + + for (int yi = 0; yi < y_center1; ++yi) { + double y = yi * y_scale; + for (int xi = 0; xi < x_center1; ++xi) { + double x = xi * x_scale; + double d2 = (x * x + y * y); + if (d2 <= min_r2) { + set_xel_a(x_center1 - 1 - xi, y_center1 - 1 - yi, fg); + set_xel_a(x_center0 + xi, y_center1 - 1 - yi, fg); + set_xel_a(x_center1 - 1 - xi, y_center0 + yi, fg); + set_xel_a(x_center0 + xi, y_center0 + yi, fg); + + } else if (d2 >= max_r2) { + set_xel_a(x_center1 - 1 - xi, y_center1 - 1 - yi, bg); + set_xel_a(x_center0 + xi, y_center1 - 1 - yi, bg); + set_xel_a(x_center1 - 1 - xi, y_center0 + yi, bg); + set_xel_a(x_center0 + xi, y_center0 + yi, bg); + + } else { + double d = sqrt(d2); + d = (d - min_radius) / (max_radius - min_radius); + d2 = d * d; + double t = (3.0 * d2) - (2.0 * d * d2); + Colord c = fg + t * (bg - fg); + + set_xel_a(x_center1 - 1 - xi, y_center1 - 1 - yi, c); + set_xel_a(x_center0 + xi, y_center1 - 1 - yi, c); + set_xel_a(x_center1 - 1 - xi, y_center0 + yi, c); + set_xel_a(x_center0 + xi, y_center0 + yi, c); + } + } + } +} + //////////////////////////////////////////////////////////////////// // Function: PNMImage::setup_rc -// Access: Public +// Access: Published // Description: Sets the _default_rc,bc,gc values appropriately // according to the color type of the image, so that // get_bright() will return a meaningful value for both diff --git a/panda/src/pnmimage/pnmImage.h b/panda/src/pnmimage/pnmImage.h index 41c335e3a6..055f287b22 100644 --- a/panda/src/pnmimage/pnmImage.h +++ b/panda/src/pnmimage/pnmImage.h @@ -144,6 +144,10 @@ PUBLISHED: INLINE void set_xel(int x, int y, double r, double g, double b); INLINE void set_xel(int x, int y, double gray); + INLINE Colord get_xel_a(int x, int y) const; + INLINE void set_xel_a(int x, int y, const Colord &value); + INLINE void set_xel_a(int x, int y, double r, double g, double b, double a); + INLINE double get_red(int x, int y) const; INLINE double get_green(int x, int y) const; INLINE double get_blue(int x, int y) const; @@ -183,6 +187,9 @@ PUBLISHED: int xfrom = 0, int yfrom = 0, int x_size = -1, int y_size = -1); + void render_spot(const Colord &fg, const Colord &bg, + double min_radius, double max_radius); + // The bodies for the non-inline *_filter() functions can be found // in the file pnm-image-filter.cxx. diff --git a/panda/src/pnmimage/pnmImageHeader.I b/panda/src/pnmimage/pnmImageHeader.I index bf634bffea..90daee6830 100644 --- a/panda/src/pnmimage/pnmImageHeader.I +++ b/panda/src/pnmimage/pnmImageHeader.I @@ -18,7 +18,7 @@ //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PNMImageHeader:: @@ -32,7 +32,7 @@ PNMImageHeader() { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::Copy Constructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PNMImageHeader:: @@ -47,7 +47,7 @@ PNMImageHeader(const PNMImageHeader ©) : //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::Copy Assignment Operator -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE void PNMImageHeader:: @@ -61,7 +61,7 @@ operator = (const PNMImageHeader ©) { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::Destructor -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// INLINE PNMImageHeader:: @@ -70,7 +70,7 @@ INLINE PNMImageHeader:: //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::get_color_type -// Access: Public +// Access: Published // Description: Returns the image type of the image, as an enumerated // value. This is really just the number of channels // cast to the enumerated type. @@ -83,7 +83,7 @@ get_color_type() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::get_num_channels -// Access: Public +// Access: Published // Description: Returns the number of channels in the image. //////////////////////////////////////////////////////////////////// INLINE int PNMImageHeader:: @@ -94,7 +94,7 @@ get_num_channels() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::is_grayscale -// Access: Public, Static +// Access: Published, Static // Description: This static variant of is_grayscale() returns true if // the indicated image type represents a grayscale // image, false otherwise. @@ -106,7 +106,7 @@ is_grayscale(PNMImageHeader::ColorType color_type) { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::is_grayscale -// Access: Public +// Access: Published // Description: Returns false if the image is a full-color image, and // has red, green, and blue components; true if it is a // grayscale image and has only a gray component. (The @@ -120,7 +120,7 @@ is_grayscale() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::has_alpha -// Access: Public, Static +// Access: Published, Static // Description: This static variant of has_alpha() returns true if // the indicated image type includes an alpha channel, // false otherwise. @@ -132,7 +132,7 @@ has_alpha(PNMImageHeader::ColorType color_type) { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::has_alpha -// Access: Public +// Access: Published // Description: Returns true if the image includes an alpha channel, // false otherwise. Unlike is_grayscale(), if this // returns false it is an error to call any of the @@ -145,7 +145,7 @@ has_alpha() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::get_maxval -// Access: Public +// Access: Published // Description: Returns the maximum channel value allowable for any // pixel in this image; for instance, 255 for a typical // 8-bit-per-channel image. A pixel with this value is @@ -158,7 +158,7 @@ get_maxval() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::get_x_size -// Access: Public +// Access: Published // Description: Returns the number of pixels in the X direction. // This is one more than the largest allowable X // coordinate. @@ -170,7 +170,7 @@ get_x_size() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::get_y_size -// Access: Public +// Access: Published // Description: Returns the number of pixels in the Y direction. // This is one more than the largest allowable Y // coordinate. @@ -182,7 +182,7 @@ get_y_size() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::has_type -// Access: Public +// Access: Published // Description: Returns true if the PNMImageHeader knows what type it // is, false otherwise. //////////////////////////////////////////////////////////////////// @@ -193,7 +193,7 @@ has_type() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::get_type -// Access: Public +// Access: Published // Description: If the file type is known (e.g. has_type() returns // true), returns its PNMFileType pointer; otherwise, // returns NULL. @@ -205,7 +205,7 @@ get_type() const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::set_type -// Access: Public +// Access: Published // Description: Sets the file type of this PNMImage. This will be // the default type used when an image is read, if the // type cannot be determined by magic number or inferred diff --git a/panda/src/pnmimage/pnmImageHeader.cxx b/panda/src/pnmimage/pnmImageHeader.cxx index a80c7a5b08..46878ca491 100644 --- a/panda/src/pnmimage/pnmImageHeader.cxx +++ b/panda/src/pnmimage/pnmImageHeader.cxx @@ -25,7 +25,7 @@ //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::read_header -// Access: Public +// Access: Published // Description: Opens up the image file and tries to read its header // information to determine its size, number of // channels, etc. If successful, updates the header @@ -46,7 +46,7 @@ read_header(const Filename &filename, PNMFileType *type) { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::make_reader -// Access: Public +// Access: Published // Description: Returns a newly-allocated PNMReader of the suitable // type for reading from the indicated image filename, // or NULL if the filename cannot be read for some @@ -94,7 +94,7 @@ make_reader(const Filename &filename, PNMFileType *type) const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::make_reader -// Access: Public +// Access: Published // Description: Returns a newly-allocated PNMReader of the suitable // type for reading from the already-opened image file, // or NULL if the file cannot be read for some reason. @@ -224,7 +224,7 @@ make_reader(istream *file, bool owns_file, const Filename &filename, //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::make_writer -// Access: Public +// Access: Published // Description: Returns a newly-allocated PNMWriter of the suitable // type for writing an image to the indicated filename, // or NULL if the filename cannot be written for some @@ -278,7 +278,7 @@ make_writer(const Filename &filename, PNMFileType *type) const { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::make_writer -// Access: Public +// Access: Published // Description: Returns a newly-allocated PNMWriter of the suitable // type for writing to the already-opened image file, or // NULL if the file cannot be written for some reason. @@ -357,7 +357,7 @@ make_writer(ostream *file, bool owns_file, const Filename &filename, //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::read_magic_number -// Access: Public, Static +// Access: Published, Static // Description: Ensures that the first n bytes of the file are read // into magic_number. If magic_number is initially // nonempty, assumes these represent the first few bytes @@ -380,7 +380,7 @@ read_magic_number(istream *file, string &magic_number, int num_bytes) { //////////////////////////////////////////////////////////////////// // Function: PNMImageHeader::output -// Access: Public +// Access: Published // Description: //////////////////////////////////////////////////////////////////// void PNMImageHeader:: diff --git a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx index b8fd345b12..5b2b5d2924 100755 --- a/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx +++ b/panda/src/wgldisplay/wglGraphicsStateGuardian.cxx @@ -86,7 +86,13 @@ framebuffer_bind_to_texture(GraphicsOutput *win, Texture *tex) { TextureContext *tc = tex->prepare_now(get_prepared_objects(), this); nassertr(tc != (TextureContext *)NULL, false); - bind_texture(tc); + CLP(TextureContext) *gtc = DCAST(CLP(TextureContext), tc); + GLenum target = get_texture_target(tex->get_texture_type()); + if (target == GL_NONE) { + // Invalid texture, can't bind it. + return false; + } + GLP(BindTexture)(target, gtc->_index); if (get_properties().is_single_buffered()) { _wglBindTexImageARB(buffer->_pbuffer, WGL_FRONT_LEFT_ARB);