/////////////////////////////////////////////////////////////////////////////// // // ## ###### // ###### ### // ## ############### Shark 3D Engine (www.shark3d.com) // ########## # # # // ######## Copyright (c) 1996-2006 Spinor GmbH. // ######### # # # All rights reserved. // ## ########## // ## // /////////////////////////////////////////////////////////////////////////////// //@cpp #include "eng_shader_std_paintmesh_clod.h" #include "eng/interf/eng_gfxstruct.h" #include "eng/interf/eng_mesh.h" #include "eng/interf/eng_gfxvar.h" #include "eng/util/eng_util_gfxutil.h" #include "eng/util/eng_util_gfxparamutil.h" #include "eng/util/eng_util_shaderutil.h" #include "eng/util/eng_util_shaderitemjob.h" #include "eng/util/eng_util_gfxinsputil.h" #include "sys/core/sys_activity.h" #include "drv/interf/drv_vartypes.h" #include "drv/util/drv_util_varutil.h" #include "util/math/util_geo_types.h" #include "util/snk/util_snk_extractutil.h" #include "util/cont/util_arrayalgo.h" #include "util/pattern/util_wildcard.h" // GAMETOOLS #include "../drv_d3d9_eng.h" //#include "GeoLodStripsLibrary.h" #include "GeoLodLibraryDLL.h" /////////////////////////////////////////////////////////////////////////////// /*@{ @declare{shadercomp.class}{eng_shader_std.paintmesh}{} This component renders a mesh. See also @ref{prog_man.shader.paintmesh}. @p @}*/ /////////////////////////////////////////////////////////////////////////////// S3D_UTIL_RTTI_TABLE_DEFINE_BEGIN(s3d_CEngShaderStdPaintMesh) S3D_UTIL_RTTI_TABLE_DEFINE_BASE(s3d_CEngShader) S3D_UTIL_RTTI_TABLE_DEFINE_BASE(s3d_CCompUtilUniqueBase) S3D_UTIL_RTTI_TABLE_DEFINE_BASE(s3d_CCompSetup) S3D_UTIL_RTTI_TABLE_DEFINE_END s3d_CEngShaderStdPaintMesh::s3d_CEngShaderStdPaintMesh() { } void s3d_CEngShaderStdPaintMesh::SetupInit( s3d_CUtilMsgHandler *MsgHandler, s3d_CUtilStr_cr Info, s3d_CCompSuppl *FetchSuppl, s3d_CUtilSnkChunk *Param) { m_Data = S3D_SYS_NEW s3d_CEngShaderStdPaintMeshData; s3d_CUtilSnkExtract SnkExtract; SnkExtract.Assign(MsgHandler, Param); m_Data->m_Info = SnkExtract.GetInfo(); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.env}{$ [str]} See @ident{comp}{eng_shader_std.group.env}. @}*/ s3d_CUtilStr EnvIdent, EnvInfo; SnkExtract.ExtractStr(EnvInfo, EnvIdent, "env", true); m_ShaderEnv = s3d_CompSupplObjT( MsgHandler, EnvInfo, FetchSuppl, EnvIdent, S3D_GENERAL_INTEROP_INTERF); if(!m_ShaderEnv) return; /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.methods} {$ [str] .. [str]} See @ref{prog_man.shader.methods}. @}*/ s3d_CUtilSnkExtractUtil::ExtractAtomSortedArray( m_Data->m_MethodArray, m_ShaderEnv->m_AtomMgr, SnkExtract, "methods", true); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.rank} {$ [int]} Rank of the shader in the rendering sequence. Shaders having a smaller rank are rendered first. @p A @em{positive} rank is used for normal rendering, a @em{negative} for rendering into a texture. Shaders with rank @em{0} are disabled. @p Theoretically, you can use any rank numbers you want. However, it is strongly recommended to use the standard rank numbers listed in @ref{prog_ref.gfxelem_ranks}. @p @}*/ m_Data->m_Rank = SnkExtract.ExtractInt("rank", true); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.back_to_front} {$ [bool]} Set rank-internal rendering order to "back to front". Default is 0. If neither @ident{comp}{eng_shader_std.paintmesh.back_to_front} nor @ident{comp}{eng_shader_std.paintmesh.front_to_back} is set, the objects are grouped by models. @}*/ m_Data->m_BackToFront = SnkExtract.ExtractBool("back_to_front", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.front_to_back} {$ [bool]} Set rank-internal rendering order to "front to back". Default is 0. See also @ident{comp}{eng_shader_std.paintmesh.back_to_front}. @}*/ m_Data->m_FrontToBack = SnkExtract.ExtractBool("front_to_back", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.paint_mode} {$ [str]} @skeyword{paint mode} @table { { @bold{Parameter value} } { @bold{Description} } } { { @code{fill} } { Filled } } { { @code{line} } { Wireframe } } { { @code{point} } { Points } } Default is "fill". @}*/ s3d_CUtilStr PaintModeStr, PaintModeInfo; SnkExtract.ExtractStr(PaintModeInfo, PaintModeStr, "paint_mode", false); m_Data->m_PaintMode = s3d_CEngUtilGfxParamUtil::ParsePaintMode( MsgHandler, PaintModeInfo, PaintModeStr, s3d_CDrvGfxEng::PaintMode_Fill); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.paint_ext} {$ [float]} If @ident{comp}{eng_shader_std.paintmesh.paint_mode} is "line", this is the width of the lines. if @ident{comp}{eng_shader_std.paintmesh.paint_mode} is "point", this is the size of the points. @}*/ m_Data->m_PaintExt = SnkExtract.ExtractFloat("paint_ext", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.cull_mode} {$ [str]} @skeyword{cull mode} Define the cull mode for this pass. Default is "back". @table { { @bold{Parameter value} } { @bold{Description} } } { { @code{none} } { Render both sides. } } { { @code{back} } { Cull back side, render the front side only. } } { { @code{front} } { Call front side, render the back side only. } } @}*/ s3d_CUtilStr CullModeStr, CullModeInfo; SnkExtract.ExtractStr(CullModeInfo, CullModeStr, "cull_mode", true); m_Data->m_CullMode = s3d_CEngUtilGfxParamUtil::ParseCullMode( MsgHandler, CullModeInfo, CullModeStr, s3d_CDrvGfxEng::CullMode_None); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.depth_test} {$ [str]} @skeyword{test mode} Depth test mode. @table { { @bold{Parameter value} } { @bold{Description} } } { { @code{never} } { false } } { { @code{equal} } { x == y } } { { @code{less} } { x < y } } { { @code{less_equal} } { x <= y } } { { @code{greater} } { x > y } } { { @code{greater_equal} } { x >= y } } { { @code{not_equal} } { x != y } } { { @code{always}} { true } } Default is "less_equal". @}*/ s3d_CUtilStr DepthTestStr, DepthTestInfo; SnkExtract.ExtractStr(DepthTestInfo, DepthTestStr, "depth_test", true); m_Data->m_DepthTest = s3d_CEngUtilGfxParamUtil::ParseTestMode( MsgHandler, DepthTestInfo, DepthTestStr, s3d_CDrvGfxEng::TestMode_Always); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.depth_write} {$ [bool]} Enabled updating the depth buffer. Default is 1. @}*/ m_Data->m_DepthWrite = SnkExtract.ExtractBool("depth_write", true); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.depth_bias_overlay} {$ [float]} A non-zero values adds an offset to the depth value which compensates rounding errors of the depth values of non-identical but coplanar polygons. This also respects polygon shifts on the screen due to the slope of the polygon and a limited sub-pixel accuracy. Per convention, a difference of +/- 1.0 means that polygons are drawn before / after the other polygons. In other words, to draw polygons before other polygons, use a depth bias which is 1.0 more than the depth bias of the other polygons. Because of this, normally the depth bias is an integer, and non-integer depth bias are only useful for platform-specific fine-tuning. @}*/ m_Data->m_DepthBiasOverlay = SnkExtract.ExtractFloat( "depth_bias_overlay", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.depth_bias_offs} {$ [float]} Assume that @code{delta_depth} is the half maximal difference of the depth values of the neighboring eight pixels and the depth of the pixel itself due to the polygon slope. Then a non-zero @code{depth_bias_offs} adds @code{delta_depth * depth_bias_offs} to the depth values generated by the polygon. This means, if a second polygon is shifted by a half pixel along the x or y screen axis, then a value of @code{depth_bias_offs = 1} compensates the change of the depth values. Note that when only resolving coplanar polyons, you don't have to use this value, but only @ident{comp}{eng_shader_std.paintmesh.depth_bias_overlay}. @}*/ m_Data->m_DepthBiasOffs = SnkExtract.ExtractFloat( "depth_bias_offs", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.fog_enabled} {$ [bool]} @skeyword{fog}. @}*/ m_Data->m_FogEnabled = SnkExtract.ExtractBool( "fog_enabled", false); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.fog_black}{$ [bool]} @skeyword{fog} Uses black as fog color instead of the real fog color. Should be used for additive rendering passes. Default is 0. @}*/ m_Data->m_FogBlack = SnkExtract.ExtractBool("fog_black", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.blend_col_src_fac} {$ [str]} @skeyword{blend} @skeyword{alpha} Define the source factor for blending the RGB component. Default for this parameter is "one". @ident{comp}{eng_shader_std.paintmesh.blend_col_op} defines how the final color is calculated. See also @ident{comp}{eng_shader_std.paintmesh.blend_col_dest_fac}. See also @ref{prog_man.shader.blending}. @p The blending modes described in the following are standard Direct3D/OpenGL blending modes. See the Direct3D or OpenGL documentation or reference for details about blending. @p @table { { @bold{Parameter value} } { @bold{Description} } } { { @code{zero} } { @code{factor = 0} } } { { @code{one} } { @code{factor = 1} } } { { @code{src_alpha} } { @code{factor = src_alpha} } } { { @code{inv_src_alpha} } { @code{factor = 1 - src_alpha} } } { { @code{src_col} } { @code{factor = src_color} } } { { @code{inv_src_col} } { @code{factor = 1 - src_color} } } { { @code{dest_alpha} } { @code{factor = dest_alpha} } } { { @code{inv_dest_alpha} } { @code{factor = 1 - dest_alpha} } } { { @code{dest_col} } { @code{factor = dest_color} } } { { @code{inv_dest_col} } { @code{factor = 1 - dest_color} } } @p @}*/ s3d_CUtilStr BlendColSrcFac, BlendColSrcFacInfo; SnkExtract.ExtractStr( BlendColSrcFacInfo, BlendColSrcFac, "blend_col_src_fac", false); m_Data->m_BlendColSrcFac = s3d_CEngUtilGfxParamUtil::ParseBlendFac( MsgHandler, BlendColSrcFacInfo, BlendColSrcFac, s3d_CDrvGfxEng::BlendFac_One); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.blend_col_dest_fac} {$ [str]} Define the destination factor for blending the RGB component. Default for this parameter is "zero". @ident{comp}{eng_shader_std.paintmesh.blend_col_op} defines how the final color is calculated. See also @ident{comp}{eng_shader_std.paintmesh.blend_col_src_fac}. See also @ref{prog_man.shader.blending}. @p The possible values are the same as for @ident{comp}{eng_shader_std.paintmesh.blend_col_src_fac}. @p @}*/ s3d_CUtilStr BlendColDestFac, BlendColDestFacInfo; SnkExtract.ExtractStr( BlendColDestFacInfo, BlendColDestFac, "blend_col_dest_fac", false); m_Data->m_BlendColDestFac = s3d_CEngUtilGfxParamUtil::ParseBlendFac( MsgHandler, BlendColDestFacInfo, BlendColDestFac, s3d_CDrvGfxEng::BlendFac_Zero); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.blend_col_op} {$ [str]} @skeyword{blend} @skeyword{alpha} Define the blend mode operation for the RGB component. Default for this parameter is "src_plus_dest". See also @ident{comp}{eng_shader_std.paintmesh.blend_col_src_fac} and @ident{comp}{eng_shader_std.paintmesh.blend_col_op}. See also @ref{prog_man.shader.blending}. The final color is calculated in the following way: The blending modes described in the following are standard Direct3D blending modes. So see an Direct3D documentation or reference for details about blending. In the following table, @code{src_interm} and @code{dest_interm} are defined in the following way, using a component-wise multiplication. @listing { src_interm = src_col * @$ @sident{comp}{eng_shader_std.paintmesh.blend_col_src_fac} dest_interm = dest_col * @$ @sident{comp}{eng_shader_std.paintmesh.blend_col_dest_fac} } @p @table { { @bold{Parameter value} } { @bold{Operation} } } { { @code{src_plus_dest} } { @code{src_interm + dest_interm} } } { { @code{src_minus_dest} } { @code{src_interm - dest_interm} } } { { @code{dest_minus_src} } { @code{dest_interm - src_interm} } } { { @code{min_src_dest} } { @code{min(src_interm, dest_interm)} } } { { @code{max_src_dest} } { @code{max(src_interm, dest_interm)} } } @p @}*/ s3d_CUtilStr BlendColOp, BlendColOpInfo; SnkExtract.ExtractStr( BlendColOpInfo, BlendColOp, "blend_col_op", false); m_Data->m_BlendColOp = s3d_CEngUtilGfxParamUtil::ParseBlendOp( MsgHandler, BlendColOpInfo, BlendColOp, s3d_CDrvGfxEng::BlendOp_SrcPlusDest); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.blend_alpha_src_fac} {$ [str]} Define the source blend mode parameter for the alpha component. See @ident{comp}{eng_shader_std.paintmesh.blend_col_src_fac}. The default is @ident{comp}{eng_shader_std.paintmesh.blend_col_src_fac}. @p @}*/ s3d_CUtilStr BlendAlphaSrcFac, BlendAlphaSrcFacInfo; SnkExtract.ExtractStr( BlendAlphaSrcFacInfo, BlendAlphaSrcFac, "blend_alpha_src_fac", false); m_Data->m_BlendAlphaSrcFac = s3d_CEngUtilGfxParamUtil::ParseBlendFac( MsgHandler, BlendAlphaSrcFacInfo, BlendAlphaSrcFac, m_Data->m_BlendColSrcFac); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.blend_alpha_dest_fac} {$ [str]} Define the destination blend mode parameter for the alpha component. See @ident{comp}{eng_shader_std.paintmesh.blend_col_dest_fac}. The default is @ident{comp}{eng_shader_std.paintmesh.blend_col_dest_fac}. @}*/ s3d_CUtilStr BlendAlphaDestFac, BlendAlphaDestFacInfo; SnkExtract.ExtractStr( BlendAlphaDestFacInfo, BlendAlphaDestFac, "blend_alpha_dest_fac", false); m_Data->m_BlendAlphaDestFac = s3d_CEngUtilGfxParamUtil::ParseBlendFac( MsgHandler, BlendAlphaDestFacInfo, BlendAlphaDestFac, m_Data->m_BlendColDestFac); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.blend_alpha_op} {$ [str]} Define the blend mode operation for the alpha component. See @ident{comp}{eng_shader_std.paintmesh.blend_col_op}. The default is @ident{comp}{eng_shader_std.paintmesh.blend_col_op}. The final alpha value is calculated in the same way as described in @ident{comp}{eng_shader_std.paintmesh.blend_col_op}, but with the following values: @listing { src_interm = src_alpha * @$ @sident{comp}{eng_shader_std.paintmesh.blend_alpha_src_fac} dest_interm = dest_alpha * @$ @sident{comp}{eng_shader_std.paintmesh.blend_alpha_dest_fac} } @p @}*/ s3d_CUtilStr BlendAlphaOp, BlendAlphaOpInfo; SnkExtract.ExtractStr( BlendAlphaOpInfo, BlendAlphaOp, "blend_alpha_op", false); m_Data->m_BlendAlphaOp = s3d_CEngUtilGfxParamUtil::ParseBlendFac( MsgHandler, BlendAlphaOpInfo, BlendAlphaOp, m_Data->m_BlendColOp); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.color}{$ [rgb]} Constant color. Default is 1. @}*/ m_Data->m_Color = s3d_CUtilSnkExtractUtil::ExtractVec3f( SnkExtract, "color", false, 1); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.color_var}{$ [float]} Instead of using the color value @ident{comp} {eng_shader_std.paintmesh.color}, use the paramer from this slot. @p You can add such parameters by a @ident{comp}{eng_shader_std.animgen} or @ident{comp}{eng_shader_std.animactu}. @}*/ s3d_CUtilSnkExtractUtil::ExtractAtom( m_Data->m_ColorVarInfo, m_Data->m_ColorVarAtom, m_ShaderEnv->m_AtomMgr, SnkExtract, "color_var", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.alpha}{$ [float]} Basis alpha value. @}*/ m_Data->m_Alpha = SnkExtract.ExtractFloat("alpha", false, 1); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.alpha_var}{$ [float]} Instead of using the alpha value @ident{comp} {eng_shader_std.paintmesh.alpha}, use the paramer from this slot. @p You can add such parameters by a @ident{comp}{eng_shader_std.animgen} or @ident{comp}{eng_shader_std.animactu}. @}*/ s3d_CUtilSnkExtractUtil::ExtractAtom( m_Data->m_AlphaVarInfo, m_Data->m_AlphaVarAtom, m_ShaderEnv->m_AtomMgr, SnkExtract, "alpha_var", false); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.coloralpha_attr_var}{$ [int]} Instead of using the color value @ident{comp} {eng_shader_std.paintmesh.color}, use the variable from this slot. @p You can add such variables by a @ident{comp}{eng_shader_std.animgen} or @ident{comp}{eng_shader_std.animactu}. @}*/ s3d_CUtilSnkExtractUtil::ExtractAtom( m_Data->m_ColorVarInfo, m_Data->m_ColorVarAtom, m_ShaderEnv->m_AtomMgr, SnkExtract, "coloralpha_attr_var", false); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.alpha_test}{$ [str]} Alpha test mode. It accepts the same values as @ident{comp}{eng_shader_std.paintmesh.depth_test}. The current fragment alpha value is tested against @ident{comp} {eng_shader_std.paintmesh.alpha_ref} using this test mode. Default is "always". @}*/ s3d_CUtilStr AlphaTestStr, AlphaTestInfo; SnkExtract.ExtractStr(AlphaTestInfo, AlphaTestStr, "alpha_test", false); m_Data->m_AlphaTestMode = s3d_CEngUtilGfxParamUtil::ParseTestMode( MsgHandler, AlphaTestInfo, AlphaTestStr, s3d_CDrvGfxEng::TestMode_Always); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.alpha_ref} {$ [float]} A reference value for alpha testing. See also @ident{comp}{eng_shader_std.paintmesh.alpha_test}. When using alpha keying 0.5 is a typical treshold value. @}*/ m_Data->m_AlphaRef = SnkExtract.ExtractFloat("alpha_ref", false, 0); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.lightarray_var} {$ [str]} Variable containing driver lights. @}*/ s3d_CUtilSnkExtractUtil::ExtractAtom( m_Data->m_LightArrayVarInfo, m_Data->m_LightArrayVarAtom, m_ShaderEnv->m_AtomMgr, SnkExtract, "lightarray_var", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.mtl}{$ [chunk]} If this chunk exists, @keyword{vertex lighting} is performed according the parameters, see @ident{comp} {}. If this chunk does not exists, no lighting is performed. @}*/ s3d_CUtilSnkChunkPtr MtlCfg = SnkExtract.ExtractChunk("mtl", false); m_Data->m_Mtl = s3d_CEngUtilLightUtil::CreateMtl( MsgHandler, MtlCfg); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.use_vertex_bone_wgh} {$ [bool]} Use the vertex normals imported with the the mesh. @}*/ m_Data->m_UseVertexBoneWgh = SnkExtract.ExtractBool("use_vertex_bone_wgh", false); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.use_vertex_bone_subscr}{$ [bool]} Use the vertex normals imported with the the mesh. @}*/ m_Data->m_UseVertexBoneSubscr = SnkExtract.ExtractBool("use_vertex_bone_subscr", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.use_vertex_point} {$ [bool]} Use the vertex normals imported with the the mesh. @}*/ m_Data->m_UseVertexPoint = SnkExtract.ExtractBool("use_vertex_point", false); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.use_vertex_normal} {$ [bool]} Use the vertex normals imported with the the mesh. @}*/ m_Data->m_UseVertexNormal = SnkExtract.ExtractBool("use_vertex_normal", false); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.use_vertex_coloralpha} {$ [bool]} Use the precalculated vertex colors imported with the the mesh. Important! When using mesh vertex colors, you cannot animate the alpha channel any more since the vertex colors include the alpha component. @}*/ m_Data->m_UseVertexColorAlpha = SnkExtract.ExtractBool("use_vertex_coloralpha", false); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.shaderprog_ident}{$ [str]} Define an optional shader program. @}*/ SnkExtract.ExtractStr( m_Data->m_ProgInfo, m_Data->m_ProgIdent, "shaderprog_ident", true); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.shaderprog_param_array} {$ [chunk] .. [chunk]} Defines which variables are passed to the shader program. See @ident{comp}{} for details. @}*/ s3d_CUtilSnkChunkArray ProgParamChunkArray; SnkExtract.ExtractChunkArray( m_Data->m_ProgParamInfo, ProgParamChunkArray, "shaderprog_param_array", true); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.texchan_var_array} {$ [str] .. [str]} Array of texture channels used for rendering. See also @ref{prog_man.shader.texture_channels}. See also @ident{comp}{eng_shader_std.modelmesh} and @ident{comp}{eng_shader_std.directtexchan} as examples on how to assign a texture channel to a variable. @p @}*/ s3d_CUtilSnkExtractUtil::ExtractAtomArray( m_Data->m_TexChanVarInfo, m_Data->m_TexChanVarAtomArray, m_ShaderEnv->m_AtomMgr, SnkExtract, "texchan_var_array", true); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.tex_attr_var_array} {$ [str] .. [str]} Each entry in this array binds the texture attributes/coordinates (as referenced by the supplied variable) to the slot corresponding to the entry's position within the array. You can then directly access these values from within your vertex shader code. Depending on the used shader language, these values are either stored in the shader code variables @code{gl_MultiTexCoordx} (OpenGL GLSL) or in your input structure's @code{TEXCOORDx} members (DirectX HLSL). @p @subsection{Example} @code{tex_attr_var_array "attr0" "tangentu" "tangentv"} @p will bind the texture attributes/coordinates referenced by variable @code{"attr0"} to @code{gl_MultiTexCoord0/TEXCOORD0}, the ones referenced by variable @code{"tangentu"} to @code{gl_MultiTexCoord1/TEXCOORD1} and the ones referenced by variable @code{"tangentv"} to @code{gl_MultiTexCoord2/TEXCOORD2}. @p @}*/ s3d_CUtilSnkExtractUtil::ExtractAtomArray( m_Data->m_AttrVarInfo, m_Data->m_AttrVarAtomArray, m_ShaderEnv->m_AtomMgr, SnkExtract, "tex_attr_var_array", true); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.attrmat_var_array} {$ [str] .. [str]} Array of names of the variables containing the mapping coordinates of the multi-texturing layers. @}*/ s3d_CUtilSnkExtractUtil::ExtractAtomArray( m_Data->m_AttrMatVarInfo, m_Data->m_AttrMatVarAtomArray, m_ShaderEnv->m_AtomMgr, SnkExtract, "attrmat_var_array", true); /*@{ @declare{shadercomp.param}{eng_shader_std.paintmesh.mesh_var}{$ [str]} Name of the variable containing the mesh which is rendered. @}*/ s3d_CUtilSnkExtractUtil::ExtractAtom( m_Data->m_MeshVarInfo, m_Data->m_MeshVarAtom, m_ShaderEnv->m_AtomMgr, SnkExtract, "mesh_var", true); /*@{ @declare{shadercomp.param} {eng_shader_std.paintmesh.insp_ident}{$ [str]} Identifier triggering a simple wireframe inspection rendering mode. For more sophisticated wireframe rendering, use @ident{comp}{eng_shader_std.modeswitch}. @}*/ m_Data->m_InspAtom = s3d_CUtilSnkExtractUtil::ExtractAtom( m_ShaderEnv->m_AtomMgr, SnkExtract, "insp_ident", false); // GAMETOOLS: load the name of the .mesh file with the LOD data SnkExtract.ExtractStr( m_Data->m_LODMeshFileInfo, m_Data->m_LODMeshFileIdent, "lodmesh", true); SnkExtract.CheckForUnknown(); s3d_CEngUtilGfxParamUtil::EvalMapProg( MsgHandler, m_Data->m_ProgParamInfo, m_ShaderEnv->m_AtomMgr, ProgParamChunkArray, m_Data->m_ProgParamMapArray); m_Data->m_Dyn = false; if(m_Data->m_ColorVarAtom) m_Data->m_Dyn = true; if(m_Data->m_AlphaVarAtom) m_Data->m_Dyn = true; if(m_Data->m_ProgIdent.IsEmpty()) { s3d_CSysIntps TexChanCnt = m_Data->m_TexChanVarAtomArray.GetCnt(); if(TexChanCnt != m_Data->m_AttrVarAtomArray.GetCnt() || TexChanCnt != m_Data->m_AttrMatVarAtomArray.GetCnt()) { s3d_CUtilMsg e; e.m_Code = "eng/shader/std" "/eng_shader_std_paintmesh.texcnt_mismatch"; e.m_StdTempl = " Sizes of texchan_var_array, tex_attr_var_array " "and attrmat_var_array differ. " "When no shaderprogram is used the array sizes " "must be equal."; e.AddInfo(m_Data->m_Info); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); } } } void s3d_CEngShaderStdPaintMesh::SetupDone() { } s3d_CUtilStr s3d_CEngShaderStdPaintMesh::GetInfo() { return m_Data->m_Info; } void s3d_CEngShaderStdPaintMesh::RegisterNotif(s3d_CUtilNotifRecip *Recip) { } s3d_CEngShaderGfxPtr s3d_CEngShaderStdPaintMesh::FindShaderGfx( s3d_CUtilNotifGather *NotifGather, s3d_CEngGfxCtx *GfxCtx) { if(!m_ShaderEnv) return 0; s3d_CEngShaderStdPaintMeshGfxPtr ShaderGfx; s3d_CEngShaderStdPaintMeshGfxTree::CNode *Pos = s3d_UtilTreeSortedGetStart(m_ShaderGfxTree, GfxCtx); if(s3d_UtilTreeIsEqualAt(Pos, GfxCtx)) ShaderGfx = Pos->m_Data.m_Val; else { ShaderGfx = S3D_SYS_NEW s3d_CEngShaderStdPaintMeshGfx( m_ShaderEnv, NotifGather, GfxCtx, m_Data); s3d_CEngShaderStdPaintMeshGfxTree::CNode *Node = ShaderGfx->GetNode(); m_ShaderGfxTree.InsertBefore(Pos, Node); } return ShaderGfx.Get(); } /////////////////////////////////////////////////////////////////////////////// s3d_CEngShaderStdPaintMeshGfx::s3d_CEngShaderStdPaintMeshGfx( s3d_CEngShaderEnv *ShaderEnv, s3d_CUtilNotifGather *NotifGather, s3d_CEngGfxCtx *GfxCtx, s3d_CEngShaderStdPaintMeshData *Data) { m_Node.m_Data.m_Key = GfxCtx; m_Node.m_Data.m_Val = this; m_ShaderEnv = ShaderEnv; m_Data = Data; s3d_CEngGfxProgMgr *GfxProgMgr = ShaderEnv->m_GfxProgMgr; if(GfxProgMgr) m_GfxProg = GfxProgMgr->CreateGfxProg( m_Data->m_ProgInfo, GfxCtx, NotifGather, m_Data->m_ProgIdent); } s3d_CEngShaderStdPaintMeshGfxTree::CNode *s3d_CEngShaderStdPaintMeshGfx::GetNode() { return &m_Node; } void s3d_CEngShaderStdPaintMeshGfx::RegisterNotif(s3d_CUtilNotifRecip *Recip) { } void s3d_CEngShaderStdPaintMeshGfx::ExtractGfx() { m_Node.Extract(); } bool s3d_CEngShaderStdPaintMeshGfx::IsValid() { if(m_GfxProg && !m_GfxProg->IsValid()) return false; s3d_CEngGfxCtx *GfxCtx = m_Node.m_Data.m_Key; s3d_CDrvGfxEng *GfxEng = GfxCtx->m_GfxEng; int GfxEngSampCnt = GfxEng->GetSampCnt(); if(GfxEngSampCnt < m_Data->m_TexChanVarAtomArray.GetCnt()) return false; return true; } void s3d_CEngShaderStdPaintMeshGfx::LinkCollect( s3d_CUtilAtomSet &VarAtomSet) { s3d_CDrvUtilVarUtil::LinkCollect( VarAtomSet, m_Data->m_ColorVarAtom); s3d_CDrvUtilVarUtil::LinkCollect( VarAtomSet, m_Data->m_AlphaVarAtom); s3d_CDrvUtilVarUtil::LinkCollect( VarAtomSet, m_Data->m_LightArrayVarAtom); s3d_CDrvUtilVarUtil::LinkCollect( VarAtomSet, m_Data->m_MeshVarAtom); s3d_CDrvUtilVarUtil::LinkCollectExport( VarAtomSet, m_Data->m_ProgParamMapArray); s3d_CDrvUtilVarUtil::LinkCollectArray( VarAtomSet, m_Data->m_TexChanVarAtomArray); s3d_CDrvUtilVarUtil::LinkCollectArray( VarAtomSet, m_Data->m_AttrVarAtomArray); s3d_CDrvUtilVarUtil::LinkCollectArray( VarAtomSet, m_Data->m_AttrMatVarAtomArray); } void s3d_CEngShaderStdPaintMeshGfx::LinkAppoint( s3d_CDrvVarDecl *VarDecl) { s3d_CDrvUtilVarUtil::LinkAppoint( m_ColorVarSlot.m_Val, VarDecl, m_Data->m_ColorVarAtom); s3d_CDrvUtilVarUtil::LinkAppoint( m_AlphaVarSlot.m_Val, VarDecl, m_Data->m_AlphaVarAtom); s3d_CDrvUtilVarUtil::LinkAppoint( m_LightArrayVarSlot.m_Val, VarDecl, m_Data->m_LightArrayVarAtom); s3d_CDrvUtilVarUtil::LinkAppoint( m_MeshVarSlot.m_Val, VarDecl, m_Data->m_MeshVarAtom); s3d_CDrvUtilVarUtil::LinkAppointExport( m_ShaderEnv->m_MsgHandler, m_Data->m_ProgParamInfo, m_ProgParamDecl, VarDecl, m_Data->m_ProgParamMapArray); s3d_CDrvUtilVarUtil::LinkAppointArray( m_TexChanVarSlotArray, VarDecl, m_Data->m_TexChanVarAtomArray); s3d_CDrvUtilVarUtil::LinkAppointArray( m_AttrVarSlotArray, VarDecl, m_Data->m_AttrVarAtomArray); s3d_CDrvUtilVarUtil::LinkAppointArray( m_AttrMatVarSlotArray, VarDecl, m_Data->m_AttrMatVarAtomArray); } s3d_CEngShaderInstPtr s3d_CEngShaderStdPaintMeshGfx::CreateShaderInst( s3d_CEngShaderHead *Head) { s3d_CEngGfxCtx *GfxCtx = m_Node.m_Data.m_Key; return S3D_SYS_NEW s3d_CEngShaderStdPaintMeshInst( m_ShaderEnv, GfxCtx, Head, this, m_GfxProg); } /////////////////////////////////////////////////////////////////////////////// s3d_CEngShaderStdPaintMeshInst::s3d_CEngShaderStdPaintMeshInst( s3d_CEngShaderEnv *ShaderEnv, s3d_CEngGfxCtx *GfxCtx, s3d_CEngShaderHead *Head, s3d_CEngShaderStdPaintMeshGfx *ShaderGfx, s3d_CEngGfxProg *GfxProg) { m_ShaderEnv = ShaderEnv; m_GfxCtx = GfxCtx; m_ShaderGfx = ShaderGfx; m_ProgGfx = GfxProg; geoIndexData = 0; lodStrips = 0; } void s3d_CEngShaderStdPaintMeshInst::RegisterNotif( s3d_CUtilNotifRecip *Recip) { } void s3d_CEngShaderStdPaintMeshInst::SetShaderCtx( s3d_CEngShaderCtx *ShaderCtx) { } void s3d_CEngShaderStdPaintMeshInst::SetGfxState(s3d_CEngGfxState *GfxState) { theGfxState=GfxState; } void s3d_CEngShaderStdPaintMeshInst::SetPos(s3d_CEngPos *Pos) { } class CustomIndexData : public Geometry::IndexData { private: /* Ogre::Mesh *targetMesh; Ogre::HardwareIndexBufferSharedPtr ibuf; Ogre::RenderOperation mRenderOp; unsigned long* pIdx;*/ void* pIdx; public: CustomIndexData(/*Ogre::Mesh *ogremesh*/):Geometry::IndexData(){ batch = NULL; pIdx = 0; /* targetMesh=ogremesh; pIdx=NULL;*/ } virtual ~CustomIndexData(void){} virtual void Begin(unsigned int submeshid, unsigned int indexcount){ assert(submeshid==0); if (batch) // esto no deberia estar: el batch nunca deberia ser nulo, debe cogese desde el constructor { // the first time (maximum capacity) the buffer is gone to bhe locked must be created /* if (pIdx16 == 0 && batch->m_IdxBufObj->m_Fmt == D3DFMT_INDEX16) pIdx16 = new unsigned short int[indexcount]; if (pIdx32 == 0 && batch->m_IdxBufObj->m_Fmt == D3DFMT_INDEX32) pIdx32 = new unsigned long int[indexcount];*/ batch->m_IdxBufObj->m_IdxCnt = indexcount; batch->m_IdxBufObj->m_PacketArray[submeshid].m_IdxCnt = batch->m_IdxBufObj->m_IdxCnt; batch->m_IdxBufObj->m_PacketArray[submeshid].m_PrimCnt = batch->m_IdxBufObj->m_PacketArray[submeshid].m_IdxCnt - 2; LPDIRECT3DINDEXBUFFER9 indexBuffer = batch->m_IdxBufObj->m_IdxBuf; HRESULT hres = indexBuffer->Lock(0,0,&pIdx,0); assert(!FAILED(hres)); } /* targetMesh->getSubMesh(submeshid)->_getRenderOperation(mRenderOp,0); ibuf = mRenderOp.indexData->indexBuffer; mRenderOp.indexData->indexCount = indexcount; pIdx = static_cast(ibuf->lock(Ogre::HardwareBuffer::HBL_NORMAL));*/ } virtual void SetIndex(unsigned int i, unsigned int index){ if (batch) // esto no deberia estar: el batch nunca deberia ser nulo, debe cogese desde el constructor { if (batch->m_IdxBufObj->m_Fmt == D3DFMT_INDEX16) { unsigned short int* pIdx16 = (unsigned short int*)pIdx; pIdx16[i] = (unsigned short)index; } if (batch->m_IdxBufObj->m_Fmt == D3DFMT_INDEX32) { unsigned long int* pIdx32 = (unsigned long int*)pIdx; pIdx32[i] = (unsigned short)index; } } /* pIdx[i] = index; //lodStripsLib->dataRetrievalInterface->GetIndex(k+offset);*/ } virtual void End(){ if (batch) // esto no deberia estar: el batch nunca deberia ser nulo, debe cogese desde el constructor { LPDIRECT3DINDEXBUFFER9 indexBuffer = batch->m_IdxBufObj->m_IdxBuf; HRESULT hres = indexBuffer->Unlock(); assert(!FAILED(hres)); } } virtual void BorrowIndexData(const Geometry::IndexData *){} // must be assigned externally when it's about to being used (before the gotoLod) and batch==0 // TODO: it should be better to pass this batch through the constructor s3d_CDrvD3d9Batch *batch; }; void s3d_CEngShaderStdPaintMeshInst::SetModel(s3d_CEngModel *Model) { if (Model) { s3d_CSharkMeshLoader *lodmodel = (s3d_CSharkMeshLoader *)Model; const Geometry::LodStripsLibraryData *lodData = lodmodel->GetLodStripsData(); geoIndexData = new CustomIndexData(); lodStrips = new Geometry::LodStripsLibrary(lodData,lodmodel->GetGeoMesh(),geoIndexData); } } void s3d_CEngShaderStdPaintMeshInst::ArrangeCollect( s3d_CUtilMemPool *MemPool, s3d_CEngShaderScopeArray &ScopeArray) { } void s3d_CEngShaderStdPaintMeshInst::ArrangeInit( s3d_CUtilMemPool *MemPool, s3d_CEngShaderScopeArray_cr ScopeArray) { // GAMETOOLS: load the .mesh file and create an instance to a LodStripsObject Geometry::GeoMeshLoader loader; Geometry::Mesh *dummyMesh = loader.load((char*)m_ShaderGfx->m_Data->m_LODMeshFileIdent.GetChars()); } void s3d_CEngShaderStdPaintMeshInst::ArrangePerform( s3d_CUtilMemPool *MemPool, s3d_CEngShaderScopeArray_cr ScopeArray) { s3d_CEngShaderStdPaintMeshGfx *ShaderGfx = m_ShaderGfx; s3d_CEngShaderStdPaintMeshData *Data = ShaderGfx->m_Data; s3d_CUtilMemPoolFrm MemPoolFrm(MemPool); s3d_CEngGfxBatchMgr *BatchMgr = m_ShaderEnv->m_GfxBatchMgr; m_BatchArray.Reset(); s3d_CSysIntps nScope = ScopeArray.GetCnt(); s3d_CSysIntps iScope; for(iScope = 0; iScope < nScope; iScope++) { s3d_CEngShaderScope *Scope = ScopeArray[iScope]; s3d_CEngGfxVarMesh *MeshVar = s3d_EngGfxVarGetMesh( m_ShaderEnv->m_MsgHandler, Data->m_MeshVarInfo.GetChars(), Scope->m_VarBlk, m_ShaderGfx->m_MeshVarSlot); if(!MeshVar) continue; s3d_CEngMeshData *MeshData = MeshVar->m_Val.m_MeshCompos.m_MeshData; s3d_CDrvSig *MeshSig = MeshVar->m_Val.m_MeshCompos.m_MeshSig; bool Complete = false; if(MeshData && MeshSig) { s3d_CDrvGfxCharge *ChargeArray = CreateChargeArray(MemPool, Scope, MeshData, true); Complete = true; bool HasBatch = false; s3d_CEngGfxBatchArray BatchArray; s3d_CSysIntps nFamily = MeshData->m_Topol.m_FamilyCnt; s3d_CSysIntps iFamily; for(iFamily = 0; iFamily < nFamily; iFamily++) { s3d_CDrvGfxCharge *Charge = 0; if(ChargeArray) Charge = &ChargeArray[iFamily]; s3d_CEngGfxBatchPtr Batch = BatchMgr->CreateBatch(m_GfxCtx, Charge); BatchArray.InsertBack(Batch); if(Batch) { HasBatch = true; if(!Batch->IsComplete()) Complete = false; } else Complete = false; } if(HasBatch) { s3d_CEngShaderStdPaintMeshBatchKeyEntry BatchEntry; BatchEntry.m_Key = MeshSig; BatchEntry.m_Val.m_BatchArray = BatchArray; BatchEntry.m_Val.m_Complete = Complete; m_BatchArray.InsertBack(BatchEntry); } } if(!Complete) { MeshVar->m_Val.m_NeedMeshData = true; s3d_CSysIntps nAttr = ShaderGfx->m_AttrVarSlotArray.GetCnt(); s3d_CSysIntps iAttr; for(iAttr = 0; iAttr < nAttr; iAttr++) { s3d_CDrvVarSlot &AttrVarSlot = ShaderGfx->m_AttrVarSlotArray.RefAt(iAttr); s3d_CEngGfxVarAttr *AttrVar = s3d_EngGfxVarGetAttr( m_ShaderEnv->m_MsgHandler, Data->m_AttrVarInfo.GetChars(), Scope->m_VarBlk, AttrVarSlot); if(AttrVar) AttrVar->m_Val.m_NeedBankData = true; } } } s3d_UtilArraySortDefault(m_BatchArray); } void s3d_CEngShaderStdPaintMeshInst::ArrangeFeedback( s3d_CUtilMemPool *MemPool, s3d_CEngShaderScopeArray_cr ScopeArray) { } void s3d_CEngShaderStdPaintMeshInst::ArrangeGather( s3d_CEngShaderExecArray &ExecArray) { s3d_CEngShaderStdPaintMeshData *Data = m_ShaderGfx->m_Data; s3d_CEngUtilShaderUtil::ArrangeGather( ExecArray, Data->m_MethodArray, this); } void s3d_CEngShaderStdPaintMeshInst::ShaderExecPerform( s3d_CEngShaderScope *Scope, s3d_CUtilAtom *Method, s3d_CEngGfxTaskArray &TaskArray) { s3d_CEngShaderStdPaintMeshGfx *ShaderGfx = m_ShaderGfx; s3d_CEngShaderStdPaintMeshData *Data = ShaderGfx->m_Data; int Rank = Data->m_Rank; if(Rank == 0) return; s3d_CEngGfxPortion *Portion = Scope->m_Portion; if(!Portion) return; s3d_CEngGfxVarMesh *MeshVar = s3d_EngGfxVarFetchWaryMesh( m_ShaderEnv->m_MsgHandler, Data->m_Info.GetChars(), Scope->m_VarBlk, ShaderGfx->m_MeshVarSlot.m_Val); if(!MeshVar) return; //////////////////////////////////////////// // GAMETOOLS: change indices and index count // GET the Batch! s3d_CEngShaderStdPaintMeshBatch *MeshBatch = 0; s3d_CDrvSig *MeshSig = MeshVar->m_Val.m_MeshCompos.m_MeshSig; if(MeshSig) { s3d_CSysIntps BatchIdx = s3d_UtilArraySortedGetEqual(m_BatchArray, MeshSig); if(BatchIdx >= 0) { s3d_CEngShaderStdPaintMeshBatchKeyEntry *BatchEntry = &m_BatchArray.RefAt(BatchIdx); MeshBatch = &BatchEntry->m_Val; } } s3d_CSysIntps FamilyCnt = 0; s3d_CDrvGfxCharge *ChargeArray = 0; const s3d_CEngGfxBatchArray *BatchArray = 0; if(MeshBatch) { BatchArray = &MeshBatch->m_BatchArray; FamilyCnt = MeshBatch->m_BatchArray.GetCnt(); } // modify the batch! // GAMETOOLS S3D_SYS_ASSERT(theGfxState); s3d_CDrvGfxEng *engine = theGfxState->GetGfxEng(); s3d_CDrvD3d9GfxEngCLOD *engineLOD = s3d_UtilRttiCastSilent(engine); S3D_SYS_ASSERT(engineLOD); if (engineLOD) { const int BatchCnt = BatchArray->GetCnt(); for (int i=0; iGetAt(i); // HAY QUE VER COMO CONSEGUIR ACCEDER A MI CLASE MODEL DESDE AQUI PARA SABER SI HAY QUE USAR STRIPS O NO // OTRA SOLUCION ES ASUMIR SIEMPRE STRIPS SI SE USA ESTE SHADER COMPONENT // s3d_CSharkMeshLoader *gtmodel = s3d_UtilRttiCastSilent(current_model); assert(lodStrips); assert(geoIndexData); s3d_CDrvD3d9Batch *BatchImpl = s3d_UtilRecogCastSilent(batch->GetDrvBatch()); if(!BatchImpl) { S3D_SYS_ASSERT(0); return; } CustomIndexData *customIndexData = (CustomIndexData*)geoIndexData; if (customIndexData->batch==0) customIndexData->batch = (s3d_CDrvD3d9Batch*)batch->GetDrvBatch(); s3d_CUtilMat4x4f auxViewMat = s3d_CUtilGeof::GetMapOfTransf3(MeshVar->m_Val.m_ViewTransf); s3d_CUtilMat4x4f viewInv = auxViewMat.GetInv(); s3d_CUtilVec3f campos(viewInv.m_xw,viewInv.m_yw,viewInv.m_zw); static float previous_lodfactor = 1.0; float distance = campos.GetLen(); float dist_max = 4; float dist_min = 0.2; float lodfactor = (float)(distance - dist_min) / (float)(dist_max - dist_min); if (lodfactor<0.0f) lodfactor=0.0f; if (lodfactor>1.0f) lodfactor=1.0f; lodfactor = 1.0f - lodfactor; /* static float ii = 0.0f; lodfactor = sinf(ii+=0.1f)*0.5f + 0.5f;*/ if (fabsf(previous_lodfactor-lodfactor)>0.01f) { lodStrips->GoToLod(lodfactor); previous_lodfactor = lodfactor; } BatchImpl->m_IdxBufObj->m_PacketArray[0].m_PrimCnt = BatchImpl->m_IdxBufObj->m_PacketArray[0].m_IdxCnt - 2; BatchImpl->m_IdxBufObj->m_D3dPrim = D3DPT_TRIANGLESTRIP; } } //////////////////////////////////////////// s3d_CEngGfxTaskOrder KeyOrder = s3d_CEngUtilGfxUtil::GetOrderOfMesh( Portion->m_Cam, Data->m_BackToFront, Data->m_FrontToBack, &MeshVar->m_Val); s3d_CEngGfxElemJob *GfxElemJob = new(m_ShaderEnv->m_MemPool) s3d_CEngUtilShaderItemJob( Scope, 0, this, &s3d_CEngShaderStdPaintMeshInst::GfxElemJobExec); s3d_CEngUtilGfxUtil::AppendTask( Portion->m_MemPool, TaskArray, Rank, KeyOrder, GfxElemJob); } void *s3d_CEngShaderStdPaintMeshInst::GfxElemJobExec( s3d_CEngShaderScope *Scope, void *GfxMark) { S3D_SYS_ACTIVITY_SOFTFRM( "s3d_CEngShaderStdPaintMeshInst::GfxElemJobExec"); s3d_CEngShaderStdPaintMeshGfx *ShaderGfx = m_ShaderGfx; s3d_CEngShaderStdPaintMeshData *Data = ShaderGfx->m_Data; if(!Scope) return GfxMark; s3d_CEngGfxPortion *Portion = Scope->m_Portion; if(!Portion) return GfxMark; s3d_CEngGfxCycle *Cycle = Portion->m_Cycle; if(!Cycle) return GfxMark; s3d_CEngGfxRun *Run = Cycle->m_Run; if(!Run) return GfxMark; s3d_CDrvGfxEng *GfxEng = Run->m_GfxEng; if(!GfxEng) return GfxMark; if(!s3d_CEngUtilGfxUtil::VerifyGfxOpen( m_ShaderEnv->m_MsgHandler, Data->m_Info.GetChars(), Cycle)) { Data->m_Rank = 0; // Avoid the error being reported each frame return GfxMark; } s3d_CEngGfxVarMesh *MeshVar = s3d_EngGfxVarFetchWaryMesh( m_ShaderEnv->m_MsgHandler, Data->m_MeshVarInfo.GetChars(), Scope->m_VarBlk, ShaderGfx->m_MeshVarSlot.m_Val); if(!MeshVar) return GfxMark; const s3d_CEngMeshData *MeshData = MeshVar->m_Val.m_MeshCompos.m_MeshData; GfxEng->SetViewRect( Cycle->m_CurViewAdapt.Concat(Portion->m_Cam.m_ViewPane)); GfxEng->SetViewDepthRange( Portion->m_Cam.m_ViewDepthStart, Portion->m_Cam.m_ViewDepthEnd); s3d_CUtilMat4x4f ViewMat = s3d_CUtilGeof::GetMapOfTransf3(MeshVar->m_Val.m_ViewTransf); GfxEng->SetTransf(s3d_CDrvGfxEng::TransfChan_View, 0, ViewMat); GfxEng->SetTransf( s3d_CDrvGfxEng::TransfChan_Proj, 0, MeshVar->m_Val.m_Proj); s3d_CSysIntps nBone = MeshVar->m_Val.m_BoneViewTransfCnt; s3d_CUtilTranslQuatf *BoneViewTransfArray = MeshVar->m_Val.m_BoneViewTransfArray; s3d_CSysIntps iBone; for(iBone = 0; iBone < nBone; iBone++) { s3d_CUtilMat4x4f DrvMat = s3d_CUtilGeof::GetMapOfTransf3(BoneViewTransfArray[iBone]); GfxEng->SetTransf(s3d_CDrvGfxEng::TransfChan_Bone, int(iBone), DrvMat); } void *KinGfxMark = Data; if(GfxMark != KinGfxMark) ExecStatic(Scope, GfxEng); s3d_CUtilVec3f Color = Data->m_Color; float Alpha = Data->m_Alpha; if(Data->m_Dyn) ExecDyn(Scope, GfxEng, Color, Alpha); if(Data->m_Mtl) ExecLighting(Scope, GfxEng, Alpha); s3d_CSysIntps nAttrMat = ShaderGfx->m_AttrMatVarSlotArray.GetCnt(); int iAttrMat; for(iAttrMat = 0; iAttrMat < nAttrMat; iAttrMat++) { s3d_CDrvVarSlot &AttrMatVarSlot = ShaderGfx->m_AttrMatVarSlotArray.RefAt(iAttrMat); s3d_CDrvVarMat4x4f *AttrMatVar = s3d_DrvVarFetchWaryMat4x4f( m_ShaderEnv->m_MsgHandler, Data->m_AttrMatVarInfo.GetChars(), Scope->m_VarBlk, AttrMatVarSlot); s3d_CUtilMat4x4f Transf = 1; if(AttrMatVar) Transf = AttrMatVar->m_Val; if(Transf != 1) GfxEng->SetTransf( s3d_CDrvGfxEng::TransfChan_Gen, iAttrMat, Transf); else GfxEng->SetTransfIdentity( s3d_CDrvGfxEng::TransfChan_Gen, iAttrMat); } int nTexChan = m_ShaderGfx->m_TexChanVarSlotArray.GetCntInt(); s3d_CEngTexChan *TexChanArray = new(Portion->m_MemPool) s3d_CEngTexChan[nTexChan]; int iTexChan; for(iTexChan = 0; iTexChan < nTexChan; iTexChan++) { s3d_CDrvVarSlot &TexChanVarSlot = m_ShaderGfx->m_TexChanVarSlotArray.RefAt(iTexChan); s3d_CEngGfxVarTexChan *TexChanVar = s3d_EngGfxVarFetchWaryTexChan( m_ShaderEnv->m_MsgHandler, Data->m_TexChanVarInfo.GetChars(), Scope->m_VarBlk, TexChanVarSlot); s3d_CEngTexChan *TexChan = &TexChanArray[iTexChan]; if(TexChanVar) *TexChan = TexChanVar->m_Val; else TexChan->Reset(); } s3d_CEngShaderStdPaintMeshBatch *MeshBatch = 0; s3d_CDrvSig *MeshSig = MeshVar->m_Val.m_MeshCompos.m_MeshSig; if(MeshSig) { s3d_CSysIntps BatchIdx = s3d_UtilArraySortedGetEqual(m_BatchArray, MeshSig); if(BatchIdx >= 0) { s3d_CEngShaderStdPaintMeshBatchKeyEntry *BatchEntry = &m_BatchArray.RefAt(BatchIdx); MeshBatch = &BatchEntry->m_Val; } } s3d_CDrvGfxParam GfxParam; GfxParam.m_Blk.m_Decl = ShaderGfx->m_ProgParamDecl; GfxParam.m_Blk.m_Data = Scope->m_VarBlk.m_Data; s3d_CSysIntps FamilyCnt = 0; s3d_CDrvGfxCharge *ChargeArray = 0; if(!MeshBatch || !MeshBatch->m_Complete) { ChargeArray = CreateChargeArray( Portion->m_MemPool, Scope, MeshData, false); if(MeshData) FamilyCnt = MeshData->m_Topol.m_FamilyCnt; } const s3d_CEngGfxBatchArray *BatchArray = 0; if(MeshBatch) { BatchArray = &MeshBatch->m_BatchArray; FamilyCnt = MeshBatch->m_BatchArray.GetCnt(); } s3d_CEngUtilGfxUtil::PaintChargeArray( GfxEng, FamilyCnt, ChargeArray, BatchArray, nTexChan, TexChanArray, GfxParam); return KinGfxMark; } s3d_CDrvGfxCharge *s3d_CEngShaderStdPaintMeshInst::CreateChargeArray( s3d_CUtilMemPool *MemPool, s3d_CEngShaderScope *Scope, const s3d_CEngMeshData *MeshData, bool Quiet) { s3d_CEngShaderStdPaintMeshGfx *ShaderGfx = m_ShaderGfx; s3d_CEngShaderStdPaintMeshData *Data = ShaderGfx->m_Data; if(!Scope) return 0; if(!MeshData) return 0; if(!m_GfxCtx) return 0; s3d_CDrvGfxEng *GfxEng = m_GfxCtx->m_GfxEng; if(!GfxEng) return 0; s3d_CSysIntps nAttr = ShaderGfx->m_AttrVarSlotArray.GetCnt(); s3d_CSysIntps MaxAttrCnt = 6 + nAttr; s3d_CDrvGfxAttr *AttrArray = new(MemPool) s3d_CDrvGfxAttr[MaxAttrCnt]; s3d_CDrvGfxAttr *Attr = AttrArray; if(Data->m_UseVertexBoneWgh && MeshData->m_Topol.m_BoneCnt > 0) { s3d_CDrvBank *Bank = MeshData->m_BoneWghAttr.m_Bank; if(!Bank) ErrorNoBoneWghBank(Data->m_Info, MeshData); Attr->m_BankDyn = MeshData->m_BoneWghAttr.m_BankDyn; Attr->m_BankSig = MeshData->m_BoneWghAttr.m_BankSig; Attr->m_Bank = Bank; Attr->m_Chan = s3d_CDrvGfxEng::AttrChan_BoneWgh; Attr->m_Slot = 0; Attr++; } if(Data->m_UseVertexBoneSubscr && MeshData->m_Topol.m_UseSubscr) { s3d_CDrvBank *Bank = MeshData->m_BoneSubscrAttr.m_Bank; if(!Bank) ErrorNoBoneSubscrBank(Data->m_Info, MeshData); Attr->m_BankDyn = MeshData->m_BoneSubscrAttr.m_BankDyn; Attr->m_BankSig = MeshData->m_BoneSubscrAttr.m_BankSig; Attr->m_Bank = Bank; Attr->m_Chan = s3d_CDrvGfxEng::AttrChan_BoneSubscr; Attr->m_Slot = 0; Attr++; } if(Data->m_UseVertexPoint) { s3d_CDrvBank *Bank = MeshData->m_PointAttr.m_Bank; if(!Bank) ErrorNoPointBank(Data->m_Info, MeshData); Attr->m_BankDyn = MeshData->m_PointAttr.m_BankDyn; Attr->m_BankSig = MeshData->m_PointAttr.m_BankSig; Attr->m_Bank = Bank; Attr->m_Chan = s3d_CDrvGfxEng::AttrChan_Point; Attr->m_Slot = 0; Attr++; } if(Data->m_UseVertexNormal) { s3d_CDrvBank *Bank = MeshData->m_NormalAttr.m_Bank; if(!Bank) ErrorNoNormalBank(Data->m_Info, MeshData); Attr->m_BankDyn = MeshData->m_NormalAttr.m_BankDyn; Attr->m_BankSig = MeshData->m_NormalAttr.m_BankSig; Attr->m_Bank = Bank; Attr->m_Chan = s3d_CDrvGfxEng::AttrChan_Normal; Attr->m_Slot = 0; Attr++; } if(Data->m_UseVertexColorAlpha) { s3d_CDrvBank *Bank = MeshData->m_ColorAlphaAttr.m_Bank; if(!Bank) ErrorNoColorAlphaBank(Data->m_Info, MeshData); Attr->m_BankDyn = MeshData->m_ColorAlphaAttr.m_BankDyn; Attr->m_BankSig = MeshData->m_ColorAlphaAttr.m_BankSig; Attr->m_Bank = Bank; Attr->m_Chan = s3d_CDrvGfxEng::AttrChan_ColorAlpha; Attr->m_Slot = 0; Attr++; } s3d_CSysIntps iAttr; for(iAttr = 0; iAttr < nAttr; iAttr++) { s3d_CDrvVarSlot &AttrVarSlot = ShaderGfx->m_AttrVarSlotArray.RefAt(iAttr); s3d_CEngGfxVarAttr *AttrVar = 0; if(Quiet) { AttrVar = s3d_EngGfxVarGetAttr( m_ShaderEnv->m_MsgHandler, Data->m_AttrVarInfo.GetChars(), Scope->m_VarBlk, AttrVarSlot); } else { AttrVar = s3d_EngGfxVarFetchWaryAttr( m_ShaderEnv->m_MsgHandler, Data->m_AttrVarInfo.GetChars(), Scope->m_VarBlk, AttrVarSlot); } if(AttrVar) { Attr->m_BankDyn = AttrVar->m_Val.m_MeshAttr.m_BankDyn; Attr->m_BankSig = AttrVar->m_Val.m_MeshAttr.m_BankSig; Attr->m_Bank = AttrVar->m_Val.m_MeshAttr.m_Bank; } Attr->m_Chan = s3d_CDrvGfxEng::AttrChan_Generic; Attr->m_Slot = int(iAttr); Attr++; } s3d_CSysIntps AttrCnt = s3d_CSysIntps(Attr - AttrArray); S3D_SYS_ASSERT(AttrCnt <= MaxAttrCnt); s3d_CDrvGfxProg *DrvProg = 0; if(m_ProgGfx) DrvProg = m_ProgGfx->GetDrvProg(); s3d_CDrvGfxCharge *ChargeArray = s3d_CEngUtilGfxUtil::CreateChargeArrayOfFamilyArray( MemPool, Data->m_Info.GetChars(), MeshData->m_Info, MeshData->m_Desc, DrvProg, MeshData->m_Topol, AttrCnt, AttrArray); return ChargeArray; } void s3d_CEngShaderStdPaintMeshInst::ExecStatic( s3d_CEngShaderScope *Scope, s3d_CDrvGfxEng *GfxEng) { if(!Scope) return; if(!GfxEng) return; s3d_CEngGfxPortion *Portion = Scope->m_Portion; if(!Portion) return; s3d_CEngShaderStdPaintMeshGfx *ShaderGfx = m_ShaderGfx; s3d_CEngShaderStdPaintMeshData *Data = ShaderGfx->m_Data; bool DoInsp = s3d_CEngUtilGfxUtil::IsModeFlagDefined( Portion->m_Cam, Data->m_InspAtom); int PaintMode = Data->m_PaintMode; if(DoInsp) { if(PaintMode == s3d_CDrvGfxEng::PaintMode_Fill) PaintMode = s3d_CDrvGfxEng::PaintMode_Line; } GfxEng->SetPaintMode(PaintMode); if(PaintMode != 0) GfxEng->SetPaintExt(Data->m_PaintExt); int CullMode = s3d_CEngUtilGfxUtil::CalcCullMode( Data->m_CullMode, Portion->m_Cam.m_Reverse); GfxEng->SetCullMode(CullMode); GfxEng->SetDepthTest(Data->m_DepthTest); GfxEng->SetDepthWrite(Data->m_DepthWrite); GfxEng->SetDepthBias( Portion->m_Cam.m_DepthBiasOverlay + Data->m_DepthBiasOverlay, Portion->m_Cam.m_DepthBiasOffs + Data->m_DepthBiasOffs); GfxEng->SetStencilMode( Portion->m_Cam.m_StencilTestMask, Portion->m_Cam.m_StencilTestRef, Portion->m_Cam.m_StencilTestMode, Portion->m_Cam.m_StencilTestMode, 0, s3d_CDrvGfxEng::StencilOp_Keep, s3d_CDrvGfxEng::StencilOp_Keep, s3d_CDrvGfxEng::StencilOp_Keep, s3d_CDrvGfxEng::StencilOp_Keep, s3d_CDrvGfxEng::StencilOp_Keep, s3d_CDrvGfxEng::StencilOp_Keep); s3d_CEngUtilGfxUtil::SetFog(GfxEng, Portion->m_Cam.m_FogDensity, Portion->m_Cam.m_FogColor, Data->m_FogEnabled, Data->m_FogBlack); GfxEng->SetBlendMode( Data->m_BlendColSrcFac, Data->m_BlendColDestFac, Data->m_BlendColOp, Data->m_BlendAlphaSrcFac, Data->m_BlendAlphaDestFac, Data->m_BlendAlphaOp); GfxEng->SetAlphaTest( Data->m_AlphaTestMode, Data->m_AlphaRef); GfxEng->SetColorAlpha(s3d_CUtilVec4f( Data->m_Color, Data->m_Alpha)); int nSamp = ShaderGfx->m_TexChanVarSlotArray.GetCntInt(); GfxEng->SetSampTexElseNone(nSamp); if(!Data->m_Mtl) GfxEng->DisableLighting(); } void s3d_CEngShaderStdPaintMeshInst::ExecDyn( s3d_CEngShaderScope *Scope, s3d_CDrvGfxEng *GfxEng, s3d_CUtilVec3f &Color, float &Alpha) { if(!Scope) return; if(!GfxEng) return; s3d_CEngGfxPortion *Portion = Scope->m_Portion; if(!Portion) return; s3d_CEngShaderStdPaintMeshGfx *ShaderGfx = m_ShaderGfx; s3d_CEngShaderStdPaintMeshData *Data = ShaderGfx->m_Data; s3d_CDrvVarVec4f *ColorVar = s3d_DrvVarFetchWaryVec4f( m_ShaderEnv->m_MsgHandler, Data->m_ColorVarInfo.GetChars(), Scope->m_VarBlk, ShaderGfx->m_ColorVarSlot.m_Val); if(ColorVar) { Color.m_x = ColorVar->m_Val.m_x; Color.m_y = ColorVar->m_Val.m_y; Color.m_z = ColorVar->m_Val.m_z; } s3d_CDrvVarVec4f *AlphaVar = s3d_DrvVarFetchWaryVec4f( m_ShaderEnv->m_MsgHandler, Data->m_AlphaVarInfo.GetChars(), Scope->m_VarBlk, ShaderGfx->m_AlphaVarSlot.m_Val); if(AlphaVar) Alpha = AlphaVar->m_Val.m_w; GfxEng->SetColorAlpha(s3d_CUtilVec4f(Color, Alpha)); } void s3d_CEngShaderStdPaintMeshInst::ExecLighting( s3d_CEngShaderScope *Scope, s3d_CDrvGfxEng *GfxEng, float Alpha) { if(!Scope) return; if(!GfxEng) return; s3d_CEngGfxPortion *Portion = Scope->m_Portion; if(!Portion) return; s3d_CEngShaderStdPaintMeshGfx *ShaderGfx = m_ShaderGfx; s3d_CEngShaderStdPaintMeshData *Data = ShaderGfx->m_Data; bool DoInsp = s3d_CEngUtilGfxUtil::IsModeFlagDefined( Portion->m_Cam, Data->m_InspAtom); s3d_CEngUtilMtl *Mtl = Data->m_Mtl; if(DoInsp) Mtl = 0; if(Mtl) { s3d_CEngGfxVarLightArray *LightArrayVar = s3d_EngGfxVarFetchWaryLightArray( m_ShaderEnv->m_MsgHandler, Data->m_LightArrayVarInfo.GetChars(), Scope->m_VarBlk, ShaderGfx->m_LightArrayVarSlot.m_Val); s3d_CDrvGfxLight **LightArray = 0; s3d_CSysIntps nLight = 0; if(LightArrayVar) { LightArray = LightArrayVar->m_Val.GetPtrRaw(); nLight = LightArrayVar->m_Val.GetCnt(); } GfxEng->SetLightArray(nLight, LightArray); GfxEng->SetMtl( Mtl->m_Ambient, Mtl->m_Diffuse, Mtl->m_Specular, Mtl->m_Emissive, Mtl->m_SpecExp, Alpha); } else GfxEng->DisableLighting(); } void s3d_CEngShaderStdPaintMeshInst::ErrorNoBoneWghBank( s3d_CUtilStr_cr Info, const s3d_CEngMeshData *MeshData) { if(!m_ShaderEnv) return; if(!MeshData) return; s3d_CUtilMsg e; e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_bonewgh_bank"; e.m_StdTempl = "Mesh \"[1]\" of object \"[2]\" " "has no bone weights. "; e.AddInfo(Info); e.AddInfo(MeshData->m_Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); e.Reset(); e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_bonewgh_bank_sic"; e.m_StdTempl = "Sic: This mesh of object \"[2]\" used by shader \"[1]\" " "has no bone weights. "; e.AddInfo(MeshData->m_Info); e.AddInfo(Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); } void s3d_CEngShaderStdPaintMeshInst::ErrorNoBoneSubscrBank( s3d_CUtilStr_cr Info, const s3d_CEngMeshData *MeshData) { if(!m_ShaderEnv) return; if(!MeshData) return; s3d_CUtilMsg e; e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_bonesubscr_bank"; e.m_StdTempl = "Mesh \"[1]\" of object \"[2]\" " "has no bone subscripts. "; e.AddInfo(Info); e.AddInfo(MeshData->m_Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); e.Reset(); e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_bonesubscr_bank_sic"; e.m_StdTempl = "Sic: This mesh of object \"[2]\" used by shader \"[1]\" " "has no bone subscripts. "; e.AddInfo(MeshData->m_Info); e.AddInfo(Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); } void s3d_CEngShaderStdPaintMeshInst::ErrorNoPointBank( s3d_CUtilStr_cr Info, const s3d_CEngMeshData *MeshData) { if(!m_ShaderEnv) return; if(!MeshData) return; s3d_CUtilMsg e; e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_point_bank"; e.m_StdTempl = "Mesh \"[1]\" of object \"[2]\" " "has no point data. "; e.AddInfo(Info); e.AddInfo(MeshData->m_Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); e.Reset(); e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_point_bank_sic"; e.m_StdTempl = "Sic: This mesh of object \"[2]\" used by shader \"[1]\" " "has no point data. "; e.AddInfo(MeshData->m_Info); e.AddInfo(Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); } void s3d_CEngShaderStdPaintMeshInst::ErrorNoNormalBank( s3d_CUtilStr_cr Info, const s3d_CEngMeshData *MeshData) { if(!m_ShaderEnv) return; if(!MeshData) return; s3d_CUtilMsg e; e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_normal_bank"; e.m_StdTempl = "Mesh \"[1]\" of object \"[2]\" " "has no normal data. "; e.AddInfo(Info); e.AddInfo(MeshData->m_Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); e.Reset(); e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_normal_bank_sic"; e.m_StdTempl = "Sic: This mesh of object \"[2]\" used by shader \"[1]\" " "has no normal data. "; e.AddInfo(MeshData->m_Info); e.AddInfo(Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); } void s3d_CEngShaderStdPaintMeshInst::ErrorNoColorAlphaBank( s3d_CUtilStr_cr Info, const s3d_CEngMeshData *MeshData) { if(!m_ShaderEnv) return; if(!MeshData) return; s3d_CUtilMsg e; e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_coloralpha_bank"; e.m_StdTempl = "Mesh \"[1]\" of object \"[2]\" " "has no color and alpha data. "; e.AddInfo(Info); e.AddInfo(MeshData->m_Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); e.Reset(); e.m_Code = "eng/shader/std/eng_shader_std_paintmesh." "no_coloralpha_bank_sic"; e.m_StdTempl = "Sic: This mesh of object \"[2]\" used by shader \"[1]\" " "has no color and alpha data. "; e.AddInfo(MeshData->m_Info); e.AddInfo(Info); e.AddInfo(MeshData->m_Desc); s3d_UtilMsgReportError(m_ShaderEnv->m_MsgHandler, e); } ///////////////////////////////////////////////////////////////////////////////