From db3ab1f6ba3e934c89631d48869e5946e176fdda Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 1 Jun 2005 20:22:24 +0000 Subject: [PATCH] multitexture --- panda/src/dxgsg8/dxGeomMunger8.I | 4 +- panda/src/dxgsg8/dxGeomMunger8.cxx | 84 +++++- panda/src/dxgsg8/dxGeomMunger8.h | 6 + panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx | 246 ++++++++++-------- panda/src/dxgsg8/dxVertexBufferContext8.cxx | 47 +++- 5 files changed, 264 insertions(+), 123 deletions(-) diff --git a/panda/src/dxgsg8/dxGeomMunger8.I b/panda/src/dxgsg8/dxGeomMunger8.I index 7711cab198..4feadab8e9 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.I +++ b/panda/src/dxgsg8/dxGeomMunger8.I @@ -24,7 +24,9 @@ //////////////////////////////////////////////////////////////////// INLINE DXGeomMunger8:: DXGeomMunger8(GraphicsStateGuardian *gsg, const RenderState *state) : - StandardMunger(gsg, state, 1, NT_packed_dabc, C_color) + StandardMunger(gsg, state, 1, NT_packed_dabc, C_color), + _texture(state->get_texture()->filter_to_max(gsg->get_max_texture_stages())), + _tex_gen(state->get_tex_gen()) { } diff --git a/panda/src/dxgsg8/dxGeomMunger8.cxx b/panda/src/dxgsg8/dxGeomMunger8.cxx index c205be5a4a..8aac838ba3 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.cxx +++ b/panda/src/dxgsg8/dxGeomMunger8.cxx @@ -49,8 +49,6 @@ munge_format_impl(const qpGeomVertexFormat *orig, const qpGeomVertexColumn *vertex_type = orig->get_vertex_column(); const qpGeomVertexColumn *normal_type = orig->get_normal_column(); const qpGeomVertexColumn *color_type = orig->get_color_column(); - const qpGeomVertexColumn *texcoord_type = - orig->get_column(InternalName::get_texcoord()); if (vertex_type != (const qpGeomVertexColumn *)NULL) { new_array_format->add_column @@ -103,13 +101,36 @@ munge_format_impl(const qpGeomVertexFormat *orig, } // To support multitexture, we will need to add all of the relevant - // texcoord types, and in the correct order (or at least in a known - // order). For now, we just add the default texcoords only. - if (texcoord_type != (const qpGeomVertexColumn *)NULL) { - new_array_format->add_column - (InternalName::get_texcoord(), texcoord_type->get_num_values(), - NT_float32, C_texcoord); - new_format->remove_column(texcoord_type->get_name()); + // texcoord types, and in the correct order. + + // Now set up each of the active texture coordinate stages--or at + // least those for which we're not generating texture coordinates + // automatically. + + // Now copy all of the texture coordinates in, in order by stage + // index. But we have to reuse previous columns. + typedef pset UsedStages; + UsedStages used_stages; + + int num_stages = _texture->get_num_on_stages(); + for (int i = 0; i < num_stages; ++i) { + TextureStage *stage = _texture->get_on_stage(i); + + const InternalName *name = stage->get_texcoord_name(); + if (used_stages.insert(name).second) { + // This is the first time we've encountered this texcoord name. + const qpGeomVertexColumn *texcoord_type = orig->get_column(name); + + if (texcoord_type != (const qpGeomVertexColumn *)NULL) { + new_array_format->add_column + (name, texcoord_type->get_num_values(), NT_float32, C_texcoord); + } else { + // We have to add something as a placeholder, even if the + // texture coordinates aren't defined. + new_array_format->add_column(name, 2, NT_float32, C_texcoord); + } + new_format->remove_column(name); + } } if (new_array_format->is_data_subset_of(*orig->get_array(0))) { @@ -123,3 +144,48 @@ munge_format_impl(const qpGeomVertexFormat *orig, new_format->insert_array(0, new_array_format); return qpGeomVertexFormat::register_format(new_format); } + +//////////////////////////////////////////////////////////////////// +// Function: DXGeomMunger8::compare_to_impl +// Access: Protected, Virtual +// Description: Called to compare two GeomMungers who are known to be +// of the same type, for an apples-to-apples comparison. +// This will never be called on two pointers of a +// different type. +//////////////////////////////////////////////////////////////////// +int DXGeomMunger8:: +compare_to_impl(const qpGeomMunger *other) const { + const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other); + if (_texture != om->_texture) { + return _texture < om->_texture ? -1 : 1; + } + if (_tex_gen != om->_tex_gen) { + return _tex_gen < om->_tex_gen ? -1 : 1; + } + + return StandardMunger::compare_to_impl(other); +} + +//////////////////////////////////////////////////////////////////// +// Function: DXGeomMunger8::geom_compare_to_impl +// Access: Protected, Virtual +// Description: Called to compare two GeomMungers who are known to be +// of the same type, for an apples-to-apples comparison. +// This will never be called on two pointers of a +// different type. +//////////////////////////////////////////////////////////////////// +int DXGeomMunger8:: +geom_compare_to_impl(const qpGeomMunger *other) const { + // Unlike GLGeomMunger, we do consider _texture and _tex_gen + // important for this purpose, since they control the number and + // order of texture coordinates we might put into the FVF. + const DXGeomMunger8 *om = DCAST(DXGeomMunger8, other); + if (_texture != om->_texture) { + return _texture < om->_texture ? -1 : 1; + } + if (_tex_gen != om->_tex_gen) { + return _tex_gen < om->_tex_gen ? -1 : 1; + } + + return StandardMunger::geom_compare_to_impl(other); +} diff --git a/panda/src/dxgsg8/dxGeomMunger8.h b/panda/src/dxgsg8/dxGeomMunger8.h index c1ccef30bd..6eeb3214c8 100644 --- a/panda/src/dxgsg8/dxGeomMunger8.h +++ b/panda/src/dxgsg8/dxGeomMunger8.h @@ -39,10 +39,16 @@ protected: virtual CPT(qpGeomVertexFormat) munge_format_impl(const qpGeomVertexFormat *orig, const qpGeomVertexAnimationSpec &animation); + virtual int compare_to_impl(const qpGeomMunger *other) const; + virtual int geom_compare_to_impl(const qpGeomMunger *other) const; + public: INLINE void *operator new(size_t size); private: + CPT(TextureAttrib) _texture; + CPT(TexGenAttrib) _tex_gen; + static qpGeomMunger *_deleted_chain; public: diff --git a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx index 93d3e054d3..9114d9c051 100644 --- a/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx +++ b/panda/src/dxgsg8/dxGraphicsStateGuardian8.cxx @@ -103,7 +103,7 @@ DXGraphicsStateGuardian8(const FrameBufferProperties &properties) : ZeroMemory(&matIdentity, sizeof(D3DMATRIX)); matIdentity._11 = matIdentity._22 = matIdentity._33 = matIdentity._44 = 1.0f; - _cur_read_pixel_buffer=RenderBuffer::T_front; + _cur_read_pixel_buffer = RenderBuffer::T_front; set_color_clear_value(_color_clear_value); // DirectX drivers seem to consistently invert the texture when @@ -113,7 +113,7 @@ DXGraphicsStateGuardian8(const FrameBufferProperties &properties) : // D3DRS_POINTSPRITEENABLE doesn't seem to support remapping the // texture coordinates via a texture matrix, so we don't advertise // GR_point_sprite_tex_matrix. - _supported_geom_rendering = + _supported_geom_rendering = qpGeom::GR_point | qpGeom::GR_point_uniform_size | qpGeom::GR_point_perspective | qpGeom::GR_point_sprite | qpGeom::GR_triangle_strip | qpGeom::GR_triangle_fan | @@ -205,22 +205,22 @@ apply_texture(int i, TextureContext *tc) { Texture *tex = tc->_texture; Texture::WrapMode wrapU, wrapV; - wrapU=tex->get_wrap_u(); - wrapV=tex->get_wrap_v(); + wrapU = tex->get_wrap_u(); + wrapV = tex->get_wrap_v(); _pD3DDevice->SetTextureStageState(i, D3DTSS_ADDRESSU, get_texture_wrap_mode(wrapU)); _pD3DDevice->SetTextureStageState(i, D3DTSS_ADDRESSV, get_texture_wrap_mode(wrapV)); - uint aniso_degree=tex->get_anisotropic_degree(); - Texture::FilterType ft=tex->get_magfilter(); + uint aniso_degree = tex->get_anisotropic_degree(); + Texture::FilterType ft = tex->get_magfilter(); _pD3DDevice->SetTextureStageState(i, D3DTSS_MAXANISOTROPY, aniso_degree); D3DTEXTUREFILTERTYPE newMagFilter; - if (aniso_degree<=1) { - newMagFilter=((ft!=Texture::FT_nearest) ? D3DTEXF_LINEAR : D3DTEXF_POINT); + if (aniso_degree <= 1) { + newMagFilter = ((ft != Texture::FT_nearest) ? D3DTEXF_LINEAR : D3DTEXF_POINT); } else { - newMagFilter=D3DTEXF_ANISOTROPIC; + newMagFilter = D3DTEXF_ANISOTROPIC; } _pD3DDevice->SetTextureStageState(i, D3DTSS_MAGFILTER, newMagFilter); @@ -243,12 +243,12 @@ apply_texture(int i, TextureContext *tc) { << "Trying to set mipmap filtering for texture with no generated mipmaps!! texname[" << tex->get_name() << "], filter(" << tex->get_minfilter() << ")\n"; - newMipFilter=D3DTEXF_NONE; + newMipFilter = D3DTEXF_NONE; } #endif - if (aniso_degree>=2) { - newMinFilter=D3DTEXF_ANISOTROPIC; + if (aniso_degree >= 2) { + newMinFilter = D3DTEXF_ANISOTROPIC; } _pD3DDevice->SetTextureStageState(i, D3DTSS_MINFILTER, newMinFilter); @@ -612,7 +612,7 @@ prepare_lens() { // The projection matrix must always be left-handed Y-up internally, // to match DirectX's convention, even if our coordinate system of // choice is otherwise. - const LMatrix4f &convert_mat = + const LMatrix4f &convert_mat = LMatrix4f::convert_mat(CS_yup_left, _current_lens->get_coordinate_system()); // DirectX also uses a Z range of 0 to 1, whereas the Panda @@ -633,7 +633,7 @@ prepare_lens() { _projection_mat *= invert_mat; } - HRESULT hr = + HRESULT hr = _pD3DDevice->SetTransform(D3DTS_PROJECTION, (D3DMATRIX*)_projection_mat.get_data()); return SUCCEEDED(hr); @@ -745,11 +745,11 @@ end_frame() { #if defined(DO_PSTATS) if (_texmgrmem_total_pcollector.is_active()) { #define TICKS_PER_GETTEXINFO (2.5*1000) // 2.5 second interval - static DWORD LastTickCount=0; - DWORD CurTickCount=GetTickCount(); + static DWORD LastTickCount = 0; + DWORD CurTickCount = GetTickCount(); if (CurTickCount-LastTickCount > TICKS_PER_GETTEXINFO) { - LastTickCount=CurTickCount; + LastTickCount = CurTickCount; report_texmgr_stats(); } } @@ -786,7 +786,7 @@ begin_draw_primitives(const qpGeom *geom, const qpGeomMunger *munger, nassertr(vbc != (VertexBufferContext *)NULL, false); apply_vertex_buffer(vbc); - const qpGeomVertexAnimationSpec &animation = + const qpGeomVertexAnimationSpec &animation = vertex_data->get_format()->get_animation(); if (animation.get_animation_type() == qpGeom::AT_hardware) { // Set up vertex blending. @@ -1387,7 +1387,7 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend HRESULT hr; if (_cur_read_pixel_buffer & RenderBuffer::T_back) { - hr=_pD3DDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pD3DSurf); + hr = _pD3DDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pD3DSurf); if (FAILED(hr)) { dxgsg8_cat.error() << "GetBackBuffer failed" << D3DERRORSTRING(hr); @@ -1424,15 +1424,15 @@ framebuffer_copy_to_ram(Texture *tex, int z, const DisplayRegion *dr, const Rend TmpSurfYsize = RECT_YSIZE(WindRect); } - hr=_pD3DDevice->CreateImageSurface(TmpSurfXsize, TmpSurfYsize, D3DFMT_A8R8G8B8, &pD3DSurf); + hr = _pD3DDevice->CreateImageSurface(TmpSurfXsize, TmpSurfYsize, D3DFMT_A8R8G8B8, &pD3DSurf); if (FAILED(hr)) { dxgsg8_cat.error() << "CreateImageSurface failed in copy_pixel_buffer()" << D3DERRORSTRING(hr); return false; } - hr=_pD3DDevice->GetFrontBuffer(pD3DSurf); + hr = _pD3DDevice->GetFrontBuffer(pD3DSurf); - if (hr==D3DERR_DEVICELOST) { + if (hr == D3DERR_DEVICELOST) { pD3DSurf->Release(); dxgsg8_cat.error() << "copy_pixel_buffer failed: device lost\n"; return false; @@ -1478,8 +1478,8 @@ reset() { set_state(RenderState::make_empty()); // want gsg to pass all state settings down so any non-matching defaults we set here get overwritten - assert(_pScrn->pD3D8!=NULL); - assert(_pD3DDevice!=NULL); + assert(_pScrn->pD3D8 != NULL); + assert(_pD3DDevice != NULL); D3DCAPS8 d3dCaps; _pD3DDevice->GetDeviceCaps(&d3dCaps); @@ -1506,6 +1506,7 @@ reset() { << "\n"; } + _max_texture_stages = d3dCaps.MaxSimultaneousTextures; _max_lights = d3dCaps.MaxActiveLights; _max_clip_planes = d3dCaps.MaxUserClipPlanes; _max_vertex_transforms = d3dCaps.MaxVertexBlendMatrices; @@ -1554,30 +1555,30 @@ reset() { _last_testcooplevel_result = D3D_OK; - for(int i=0;ipD3D8->CheckDeviceFormat(_pScrn->CardIDNum, D3DDEVTYPE_HAL, _pScrn->DisplayMode.Format, 0x0, D3DRTYPE_TEXTURE, g_D3DFORMATmap[fmtflag]); if (SUCCEEDED(hr)){ - _pScrn->SupportedTexFmtsMask|=fmtflag; + _pScrn->SupportedTexFmtsMask |= fmtflag; } } // s3 virge drivers sometimes give crap values for these - if (_pScrn->d3dcaps.MaxTextureWidth==0) - _pScrn->d3dcaps.MaxTextureWidth=256; + if (_pScrn->d3dcaps.MaxTextureWidth == 0) + _pScrn->d3dcaps.MaxTextureWidth = 256; - if (_pScrn->d3dcaps.MaxTextureHeight==0) - _pScrn->d3dcaps.MaxTextureHeight=256; + if (_pScrn->d3dcaps.MaxTextureHeight == 0) + _pScrn->d3dcaps.MaxTextureHeight = 256; if (_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGTABLE) { // watch out for drivers that emulate per-pixel fog with per-vertex fog (Riva128, Matrox Millen G200) // some of these require gouraud-shading to be set to work, as if you were using vertex fog - _doFogType=PerPixelFog; + _doFogType = PerPixelFog; } else { // every card is going to have vertex fog, since it's implemented in d3d runtime - assert((_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX)!=0); + assert((_pScrn->d3dcaps.RasterCaps & D3DPRASTERCAPS_FOGVERTEX) != 0); // vtx fog may look crappy if you have large polygons in the foreground and they get clipped, // so you may want to disable it @@ -1593,7 +1594,7 @@ reset() { } } - _pScrn->bCanDirectDisableColorWrites=((_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE)!=0); + _pScrn->bCanDirectDisableColorWrites = ((_pScrn->d3dcaps.PrimitiveMiscCaps & D3DPMISCCAPS_COLORWRITEENABLE) != 0); // Lighting, let's turn it off by default _pD3DDevice->SetRenderState(D3DRS_LIGHTING, false); @@ -1656,7 +1657,7 @@ reset() { void DXGraphicsStateGuardian8:: apply_fog(Fog *fog) { - if (_doFogType==None) + if (_doFogType == None) return; Fog::Mode panda_fogmode = fog->get_mode(); @@ -1728,7 +1729,7 @@ issue_alpha_test(const AlphaTestAttrib *attrib) { if (mode == AlphaTestAttrib::M_none) { enable_alpha_test(false); } else { - // AlphaTestAttrib::PandaCompareFunc === D3DCMPFUNC + // AlphaTestAttrib::PandaCompareFunc == = D3DCMPFUNC call_dxAlphaFunc((D3DCMPFUNC)mode, attrib->get_reference_alpha()); enable_alpha_test(true); } @@ -1826,7 +1827,7 @@ issue_rescale_normal(const RescaleNormalAttrib *attrib) { void DXGraphicsStateGuardian8:: issue_color_write(const ColorWriteAttrib *attrib) { _color_write_mode = attrib->get_mode(); - set_color_writemask((_color_write_mode ==ColorWriteAttrib::M_on) ? 0xFFFFFFFF : 0x0); + set_color_writemask((_color_write_mode == ColorWriteAttrib::M_on) ? 0xFFFFFFFF : 0x0); } //////////////////////////////////////////////////////////////////// @@ -1918,24 +1919,8 @@ issue_depth_offset(const DepthOffsetAttrib *attrib) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: issue_tex_gen(const TexGenAttrib *attrib) { - TexGenAttrib::Mode mode = attrib->get_mode(TextureStage::get_default()); - switch (mode) { - case TexGenAttrib::M_off: - _pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); - _pD3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); - break; - - case TexGenAttrib::M_eye_sphere_map: - _pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, - D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); - _pD3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, FALSE); - break; - - case TexGenAttrib::M_point_sprite: - _pD3DDevice->SetTextureStageState(0, D3DTSS_TEXCOORDINDEX, 0); - _pD3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, TRUE); - break; - } + _current_tex_gen = attrib; + _texture_stale = true; } //////////////////////////////////////////////////////////////////// @@ -2200,40 +2185,96 @@ do_issue_texture() { _texture_involves_color_scale = false; + // We have to match up the texcoord stage index to the order written + // out by the DXGeomMunger. This means the texcoord names are + // written in the order they are referenced by the TextureAttrib, + // except that if a name is repeated its index number is reused from + // the first time. + typedef pmap UsedTexcoordIndex; + UsedTexcoordIndex used_texcoord_index; + int i; for (i = 0; i < num_stages; i++) { TextureStage *stage = new_texture->get_on_stage(i); Texture *texture = new_texture->get_on_texture(stage); nassertv(texture != (Texture *)NULL); - if (i >= num_old_stages || - stage != _current_texture->get_on_stage(i) || - texture != _current_texture->get_on_texture(stage) || - stage->involves_color_scale()) { - // Stage i has changed. Issue the texture on this stage. - TextureContext *tc = texture->prepare_now(_prepared_objects, this); - apply_texture(i, tc); + const InternalName *name = stage->get_texcoord_name(); - set_texture_blend_mode(i, stage); + // This pair of lines will get the next consecutive texcoord index + // number if this is the first time we have referenced this + // particular texcoord name; otherwise, it will return the same + // index number it returned before. + UsedTexcoordIndex::iterator ti = used_texcoord_index.insert(UsedTexcoordIndex::value_type(name, (int)used_texcoord_index.size())).first; + int texcoord_index = (*ti).second; - if (_current_tex_mat->has_stage(stage)) { - // We have to reorder the elements of the matrix for some reason. - const LMatrix4f &m = _current_tex_mat->get_mat(stage); - LMatrix4f dm(m(0, 0), m(0, 1), m(0, 3), 0.0f, - m(1, 0), m(1, 1), m(1, 3), 0.0f, - m(3, 0), m(3, 1), m(3, 3), 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f); - _pD3DDevice->SetTransform(get_tex_mat_sym(i), (D3DMATRIX *)dm.get_data()); - _pD3DDevice->SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, - D3DTTFF_COUNT2); - } else { - _pD3DDevice->SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, - D3DTTFF_DISABLE); - // For some reason, "disabling" texture coordinate transforms - // doesn't seem to be sufficient. We'll load an identity matrix - // to underscore the point. - _pD3DDevice->SetTransform(get_tex_mat_sym(i), &matIdentity); + // We always reissue every stage in DX, just in case the texcoord + // index or texgen mode or some other property has changed. + TextureContext *tc = texture->prepare_now(_prepared_objects, this); + apply_texture(i, tc); + set_texture_blend_mode(i, stage); + + bool has_tex_mat = false; + LMatrix4f tex_mat; + + if (_current_tex_mat->has_stage(stage)) { + // We have to reorder the elements of the matrix for some reason. + const LMatrix4f &m = _current_tex_mat->get_mat(stage); + tex_mat.set(m(0, 0), m(0, 1), m(0, 3), 0.0f, + m(1, 0), m(1, 1), m(1, 3), 0.0f, + m(3, 0), m(3, 1), m(3, 3), 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f); + has_tex_mat = true; + } + + // Issue the texgen mode. + TexGenAttrib::Mode mode = _current_tex_gen->get_mode(stage); + bool any_point_sprite = false; + switch (mode) { + case TexGenAttrib::M_off: + _pD3DDevice->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index); + break; + + case TexGenAttrib::M_eye_sphere_map: + { + _pD3DDevice->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, + texcoord_index | D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR); + // This texture matrix, applied on top of the texcoord + // computed by D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR, + // approximates the effect produced by OpenGL's GL_SPHERE_MAP. + LMatrix4f sphere_map(0.33f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.33f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.5f, 0.5f, 0.0f, 1.0f); + + if (has_tex_mat) { + tex_mat = sphere_map * tex_mat; + } else { + tex_mat = sphere_map; + has_tex_mat = true; + } } + break; + + case TexGenAttrib::M_point_sprite: + _pD3DDevice->SetTextureStageState(i, D3DTSS_TEXCOORDINDEX, texcoord_index); + any_point_sprite = true; + break; + } + + _pD3DDevice->SetRenderState(D3DRS_POINTSPRITEENABLE, any_point_sprite); + + if (has_tex_mat) { + _pD3DDevice->SetTransform(get_tex_mat_sym(i), (D3DMATRIX *)tex_mat.get_data()); + _pD3DDevice->SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, + D3DTTFF_COUNT2); + } else { + _pD3DDevice->SetTextureStageState(i, D3DTSS_TEXTURETRANSFORMFLAGS, + D3DTTFF_DISABLE); + // For some reason, "disabling" texture coordinate transforms + // doesn't seem to be sufficient. We'll load an identity matrix + // to underscore the point. + _pD3DDevice->SetTransform(get_tex_mat_sym(i), &matIdentity); } } @@ -2243,11 +2284,6 @@ do_issue_texture() { } _current_texture = new_texture; - - // Changing the set of texture stages will require us to reissue the - // texgen and texmat attribs. - _needs_tex_gen = true; - _needs_tex_mat = true; } //////////////////////////////////////////////////////////////////// @@ -2484,13 +2520,13 @@ free_d3d_device() { _bDXisReady = false; - if (_pD3DDevice!=NULL) - for(int i=0;iSetTexture(i, NULL); // d3d should release this stuff internally anyway, but whatever release_all(); - if (_pD3DDevice!=NULL) + if (_pD3DDevice != NULL) RELEASE(_pD3DDevice, dxgsg8, "d3dDevice", RELEASE_DOWN_TO_ZERO); free_nondx_resources(); @@ -2521,9 +2557,9 @@ void DXGraphicsStateGuardian8:: set_read_buffer(const RenderBuffer &rb) { if (rb._buffer_type & RenderBuffer::T_front) { - _cur_read_pixel_buffer=RenderBuffer::T_front; + _cur_read_pixel_buffer = RenderBuffer::T_front; } else if (rb._buffer_type & RenderBuffer::T_back) { - _cur_read_pixel_buffer=RenderBuffer::T_back; + _cur_read_pixel_buffer = RenderBuffer::T_back; } else { dxgsg8_cat.error() << "Invalid or unimplemented Argument to set_read_buffer!\n"; } @@ -2701,9 +2737,9 @@ report_texmgr_stats() { if (!tex_stats_retrieval_impossible) { hr = _pD3DDevice->GetInfo(D3DDEVINFOID_RESOURCEMANAGER, &all_resource_stats, sizeof(D3DDEVINFO_RESOURCEMANAGER)); - if (hr!=D3D_OK) { - if (hr==S_FALSE) { - static int PrintedMsg=2; + if (hr != D3D_OK) { + if (hr == S_FALSE) { + static int PrintedMsg = 2; if (PrintedMsg>0) { if (dxgsg8_cat.is_debug()) { dxgsg8_cat.debug() @@ -2756,7 +2792,7 @@ set_context(DXScreenData *new_context) { //////////////////////////////////////////////////////////////////// void DXGraphicsStateGuardian8:: set_render_target() { - LPDIRECT3DSURFACE8 pBack=NULL, pStencil=NULL; + LPDIRECT3DSURFACE8 pBack = NULL, pStencil = NULL; if (!_pSwapChain) //maybe fullscreen mode or main/single window _pD3DDevice->GetBackBuffer(0, D3DBACKBUFFER_TYPE_MONO, &pBack); @@ -2789,20 +2825,20 @@ set_texture_blend_mode(int i, const TextureStage *stage) { // want to multiply tex-color*pixel color to emulate GL modulate blend (see glTexEnv) _pD3DDevice->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_MODULATE); _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); - _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE); _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT); break; case TextureStage::M_decal: // emulates GL_DECAL glTexEnv mode _pD3DDevice->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_BLENDTEXTUREALPHA); _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); - _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); - _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_CURRENT); break; case TextureStage::M_replace: @@ -2816,13 +2852,13 @@ set_texture_blend_mode(int i, const TextureStage *stage) { case TextureStage::M_add: _pD3DDevice->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_ADD); _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG1, D3DTA_TEXTURE); - _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + _pD3DDevice->SetTextureStageState(i, D3DTSS_COLORARG2, D3DTA_CURRENT); // since I'm making up 'add' mode, use modulate. "adding" alpha // never makes sense right? _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_MODULATE); _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); - _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + _pD3DDevice->SetTextureStageState(i, D3DTSS_ALPHAARG2, D3DTA_CURRENT); break; case TextureStage::M_blend: @@ -2908,7 +2944,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *pPresParams, DXScreenData **pScrn) { _PresReset.BackBufferHeight = pPresParams->BackBufferHeight; } - hr=_pD3DDevice->Reset(&_PresReset); + hr = _pD3DDevice->Reset(&_PresReset); if (FAILED(hr)) { return hr; } @@ -2917,7 +2953,7 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *pPresParams, DXScreenData **pScrn) { if (pScrn) *pScrn = NULL; - if (pPresParams!=&_pScrn->PresParams) + if (pPresParams != &_pScrn->PresParams) memcpy(&_pScrn->PresParams, pPresParams, sizeof(D3DPRESENT_PARAMETERS)); return hr; } @@ -2927,10 +2963,10 @@ reset_d3d_device(D3DPRESENT_PARAMETERS *pPresParams, DXScreenData **pScrn) { _pScrn->pSwapChain->Release(); wdxdisplay8_cat.debug() << "SwapChain " << _pScrn->pSwapChain << " is released\n"; _pScrn->pSwapChain = NULL; - hr=_pD3DDevice->CreateAdditionalSwapChain(pPresParams, &_pScrn->pSwapChain); + hr = _pD3DDevice->CreateAdditionalSwapChain(pPresParams, &_pScrn->pSwapChain); } if (SUCCEEDED(hr)) { - if (pPresParams!=&_pScrn->PresParams) + if (pPresParams != &_pScrn->PresParams) memcpy(&_pScrn->PresParams, pPresParams, sizeof(D3DPRESENT_PARAMETERS)); if (pScrn) *pScrn = _pScrn; @@ -2956,7 +2992,7 @@ check_cooperative_level() { switch(hr) { case D3DERR_DEVICENOTRESET: _bDXisReady = false; - hr=reset_d3d_device(&_pScrn->PresParams); + hr = reset_d3d_device(&_pScrn->PresParams); if (FAILED(hr)) { // I think this shouldnt fail unless I've screwed up the PresParams from the original working ones somehow dxgsg8_cat.error() diff --git a/panda/src/dxgsg8/dxVertexBufferContext8.cxx b/panda/src/dxgsg8/dxVertexBufferContext8.cxx index 07c0c619e5..73c05d177f 100644 --- a/panda/src/dxgsg8/dxVertexBufferContext8.cxx +++ b/panda/src/dxgsg8/dxVertexBufferContext8.cxx @@ -106,29 +106,60 @@ DXVertexBufferContext8(qpGeomVertexArrayData *data) : ++n; } - // For multitexture support, we will need to look for all of the - // texcoord names and enable them in order. - if (n < num_columns && - array_format->get_column(n)->get_name() == InternalName::get_texcoord()) { + // Now look for all of the texcoord names and enable them in the + // same order they appear in the array. + int texcoord_index = 0; + while (n < num_columns && + array_format->get_column(n)->get_contents() == qpGeom::C_texcoord) { const qpGeomVertexColumn *column = array_format->get_column(n); switch (column->get_num_values()) { case 1: - _fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE1(0); + _fvf |= D3DFVF_TEXCOORDSIZE1(texcoord_index); ++n; break; case 2: - _fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE2(0); + _fvf |= D3DFVF_TEXCOORDSIZE2(texcoord_index); ++n; break; case 3: - _fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0); + _fvf |= D3DFVF_TEXCOORDSIZE3(texcoord_index); ++n; break; case 4: - _fvf |= D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE4(0); + _fvf |= D3DFVF_TEXCOORDSIZE4(texcoord_index); ++n; break; } + ++texcoord_index; + } + + switch (texcoord_index) { + case 0: + break; + case 1: + _fvf |= D3DFVF_TEX1; + break; + case 2: + _fvf |= D3DFVF_TEX2; + break; + case 3: + _fvf |= D3DFVF_TEX3; + break; + case 4: + _fvf |= D3DFVF_TEX4; + break; + case 5: + _fvf |= D3DFVF_TEX5; + break; + case 6: + _fvf |= D3DFVF_TEX6; + break; + case 7: + _fvf |= D3DFVF_TEX7; + break; + case 8: + _fvf |= D3DFVF_TEX8; + break; } }