/// 指定 BasicProgram と、指定 BasicMaterial を必ず利用して描画する public void Draw(GraphicsContext graphics, BasicProgram program, BasicMaterial material, Matrix4 viewProj) { List <LocalPart> localPartList = updateLocalPart(); // パーツを DrawOrder 順にソート localPartList.Sort(); setPolygonMode(graphics, material); graphics.SetShaderProgram(program); program.SetViewProj(viewProj); program.SetMaterial(ref material); setLayers(graphics, program, material); // パーツの描画 foreach (LocalPart localPart in localPartList) { program.SetMatrixPalette(localPart.worldCount, ref localPart.matrixPalette); program.Update(); graphics.SetVertexBuffer(0, localPart.vertexBuffer); graphics.DrawArrays(localPart.primitives); } }
/// DrawParts 内の、mesh を DrawOrder ごとに並び替える /** * note : DrawPart をまたぐようなソートは行わない点に注意すること. */ public void SortDrawParts() { foreach (var bone in Bones) { List <Part> partList = new List <Part>(); foreach (var index in bone.DrawParts) { BasicPart part = Parts[index]; foreach (var mesh in part.Meshes) { BasicMaterial material = Materials[mesh.Material]; partList.Add(new Part(mesh, material.DrawOrder)); } // パーツを DrawOrder 順にソート partList.Sort(delegate(Part lhs, Part rhs){ return(lhs.drawOrder - rhs.drawOrder); }); int i = 0; foreach (var sortedPart in partList) { part.Meshes[i] = sortedPart.mesh; i++; } } } }
/// Material::Layer が保持する TexAnim用Matrix の対象 Bone を探して index を格納しておく public void BindTexAnimBone() { foreach (BasicPart part in Parts) { foreach (var mesh in part.Meshes) { if (mesh.Material >= 0) { BasicMaterial material = Materials[mesh.Material]; for (int i = 0; i < material.Layers.Length; i++) { BasicLayer layer = material.Layers[i]; // 隠しておいた名前から、Bone の index を確定させる if (layer.TexAnimBoneName != "") { for (int bi = 0; bi < Bones.Length; bi++) { // Console.WriteLine(Bones[bi].Name); if (layer.TexAnimBoneName == Bones[bi].Name) { layer.TexAnimBoneIdx = bi; material.UseTexAnim = true; } } } else { layer.TexAnimBoneIdx = -1; } } } } } }
void UpdateBone(BasicMotion motion) { float weight = 1.0f; float[] value = new float[4]; foreach (var fcurve in motion.FCurves) { if (fcurve.TargetType == BasicFCurveTargetType.Bone) { EvalFCurve(fcurve, motion.Frame, value); BasicBone bone = Bones[fcurve.TargetIndex]; switch (fcurve.ChannelType) { case BasicFCurveChannelType.Translation: Vector3 translation = new Vector3(value[0], value[1], value[2]); bone.Translation = bone.Translation.Lerp(translation, weight); break; case BasicFCurveChannelType.Rotation: Quaternion rotation; if (fcurve.DimCount == 4) { rotation = new Quaternion(value[0], value[1], value[2], value[3]); } else { Vector3 angles = new Vector3(value[0], value[1], value[2]); // [note] 旧API // rotation = Quaternion.FromEulerAnglesZYX( angles ) ; rotation = Quaternion.RotationZyx(angles); } // [note] 旧API // bone.Rotation = Quaternion.Slerp( bone.Rotation, rotation, weight, 0.0f ) ; bone.Rotation = bone.Rotation.Slerp(rotation, weight); break; case BasicFCurveChannelType.Scaling: Vector3 scaling = new Vector3(value[0], value[1], value[2]); bone.Scaling = bone.Scaling.Lerp(scaling, weight); break; } } else if (fcurve.TargetType == BasicFCurveTargetType.Material) { EvalFCurve(fcurve, motion.Frame, value); BasicMaterial material = Materials[fcurve.TargetIndex]; switch (fcurve.ChannelType) { // 追加 case BasicFCurveChannelType.Diffuse: material.Diffuse.X = value[0]; material.Diffuse.Y = value[1]; material.Diffuse.Z = value[2]; material.Diffuse.W = value[3]; break; } } } }
void LoadMaterial(Chunk chunk, BasicMaterial material) { int nLayers = CountChild(chunk, ChunkType.Layer); material.Layers = new BasicLayer[nLayers]; for (int i = 0; i < nLayers; i++) { material.Layers[i] = new BasicLayer(); } int iLayer = 0; material.Name = chunk.Name; Chunk child; for (int pos = chunk.Child; pos < chunk.Next; pos = child.Next) { child = ReadChunk(pos); int args = child.Args; switch (child.Type) { case ChunkType.Layer: LoadLayer(child, chunk, material.Layers[iLayer++]); break; case ChunkType.Diffuse: // 変更 Vector3 -> Vector4 material.Diffuse = ReadVector4(args + 0); material.Opacity = ReadFloat(args + 12); break; case ChunkType.Specular: // 変更 Vector3 -> Vector4 material.Specular = ReadVector4(args + 0); material.Shininess = ReadFloat(args + 16); break; case ChunkType.Ambient: // 変更 Vector3 -> Vector4 material.Ambient = ReadVector4(args + 0); material.Opacity = ReadFloat(args + 12); break; case ChunkType.Emission: // 変更 Vector3 -> Vector4 material.Emission = ReadVector4(args); break; case ChunkType.BlindData: ReadMaterialBlindData(material, child.Args, child.Args + child.ArgsSize); break; } } }
private void setPolygonMode(GraphicsContext graphics, BasicMaterial material) { graphics.SetBlendFunc((BlendFuncMode)material.BlendFuncMode, (BlendFuncFactor)material.SrcBlendFactor, (BlendFuncFactor)material.DstBlendFactor); graphics.SetPolygonOffset(material.PolyOffsetFactor / 1000.0f, material.PolyOffsetUnits / 1000.0f); // Depth Test graphics.Enable(EnableMode.DepthTest, material.DepthTest != 0); graphics.SetDepthFunc((DepthFuncMode)material.DepthMode, material.DepthWrite != 0); graphics.Enable(EnableMode.CullFace, (CullFaceMode)material.CullFaceMode != CullFaceMode.None); graphics.SetCullFace((CullFaceMode)material.CullFaceMode, (CullFaceDirection)material.CullFaceDirection); }
/// Matrial + WorldCount + LightCount から利用するシェーダを検索する public BasicProgram findBasicProgram(ShaderContainer shaderContainer, BasicMaterial material, int worldCount, int lightCount) { BasicProgram program; if (material.BasicShader[worldCount, lightCount] == null) { if (material.ShaderName == "" || material.ShaderName == "basic") { if (material.ShaderNameObj == null) { material.ShaderNameObj = new BasicShaderName(worldCount, this.lightCount, material); } else { material.ShaderNameObj.SetWorldAndLight(worldCount, this.lightCount); } program = shaderContainer.Find(material.ShaderNameObj); material.BasicShader[worldCount, lightCount] = program; } else { // 特殊 program = shaderContainer.Find(material.ShaderName); material.BasicShader[worldCount, lightCount] = program; // uniform foreach (KeyValuePair <string, int> entry in material.BlindData) { int id = program.FindUniform(entry.Key); if (id >= 0) { program.SetUniformValue(id, entry.Value / 1000.0f); } } } } else { program = material.BasicShader[worldCount, lightCount]; } return(program); }
public void SetMaterial(ref BasicMaterial material) { if (idIKAmbient >= 0) { this.SetUniformValue(idIKAmbient, ref material.Ambient); } if (idIDiffuse >= 0) { this.SetUniformValue(idIDiffuse, ref material.Diffuse); } if (idISpecular >= 0) { this.SetUniformValue(idISpecular, ref material.Specular); } if (idShininess >= 0) { this.SetUniformValue(idShininess, 80.8f); } if (idAlphaThreshold >= 0) { this.SetUniformValue(idAlphaThreshold, material.AlphaThreshold); } }
/// void ReadMaterialBlindData(BasicMaterial material, int pos, int end) { int term = pos; while (term < end && fileImage[term] != 0) { term++; } string name = ""; if (term != pos) { name = encoding.GetString(fileImage, pos, term - pos); } int val = ReadInt32(term + (4 - (term % 4))); // material.BlindData[ name ] = val; if (name == "CullFaceMode") { material.CullFaceMode = val; } else if (name == "CullFaceDirection") { material.CullFaceDirection = val; } else if (name == "DrawOrder") { material.DrawOrder = val; } else if (name == "BlendFuncMode") { material.BlendFuncMode = val; } else if (name == "SrcBlendFactor") { material.SrcBlendFactor = val; } else if (name == "DstBlendFactor") { material.DstBlendFactor = val; } else if (name == "DepthWrite") { material.DepthWrite = val; } else if (name == "DepthMode") { material.DepthMode = val; } else if (name == "DepthTest") { material.DepthTest = val; } else if (name == "PolyOffsetFactor") { material.PolyOffsetFactor = val; } else if (name == "PolyOffsetUnits") { material.PolyOffsetUnits = val; } else if (name == "AlphaThreshold") { material.AlphaThreshold = val / 1000.0f; } else if (name == "LightEnable") { material.LightEnable = val; } else if (name == "VertexColorEnable") { material.VertexColorEnable = val; } else { // 意味のある BliendData if (val == 4803) { material.ShaderName = name; } else { // 意味のない BliendData material.BlindData.Add(name, val); } } }
private void setPolygonMode( GraphicsContext graphics, BasicMaterial material ) { graphics.SetBlendFunc( (BlendFuncMode)material.BlendFuncMode, (BlendFuncFactor)material.SrcBlendFactor, (BlendFuncFactor)material.DstBlendFactor ); graphics.SetPolygonOffset( material.PolyOffsetFactor / 1000.0f, material.PolyOffsetUnits / 1000.0f ); // Depth Test graphics.Enable( EnableMode.DepthTest, material.DepthTest != 0 ); graphics.SetDepthFunc( (DepthFuncMode)material.DepthMode, material.DepthWrite != 0 ); graphics.Enable( EnableMode.CullFace, (CullFaceMode)material.CullFaceMode != CullFaceMode.None); graphics.SetCullFace( (CullFaceMode)material.CullFaceMode, (CullFaceDirection)material.CullFaceDirection ); }
/// void ReadMaterialBlindData( BasicMaterial material, int pos, int end ) { int term = pos ; while ( term < end && fileImage[ term ] != 0 ){ term ++ ; } string name = ""; if( term != pos ){ name = encoding.GetString( fileImage, pos, term - pos ) ; } int val = ReadInt32( term + (4 - (term % 4)) ); // material.BlindData[ name ] = val; if( name == "CullFaceMode" ){ material.CullFaceMode = val; }else if( name == "CullFaceDirection" ){ material.CullFaceDirection = val; }else if( name == "DrawOrder" ){ material.DrawOrder = val; }else if( name == "BlendFuncMode" ){ material.BlendFuncMode = val; }else if( name == "SrcBlendFactor" ){ material.SrcBlendFactor = val; }else if( name == "DstBlendFactor" ){ material.DstBlendFactor = val; }else if( name == "DepthWrite" ){ material.DepthWrite = val; }else if( name == "DepthMode" ){ material.DepthMode = val; }else if( name == "DepthTest" ){ material.DepthTest = val; }else if( name == "PolyOffsetFactor" ){ material.PolyOffsetFactor = val; }else if( name == "PolyOffsetUnits" ){ material.PolyOffsetUnits = val; }else if( name == "AlphaThreshold" ){ material.AlphaThreshold = val / 1000.0f; }else if( name == "LightEnable" ){ material.LightEnable = val; }else if( name == "VertexColorEnable" ){ material.VertexColorEnable = val; }else{ // 意味のある BliendData if( val == 4803 ){ material.ShaderName = name; }else{ // 意味のない BliendData material.BlindData.Add( name, val ); } } }
/// Matrial + WorldCount + LightCount から利用するシェーダを検索する public BasicProgram findBasicProgram( ShaderContainer shaderContainer, BasicMaterial material, int worldCount, int lightCount ) { BasicProgram program; if( material.BasicShader[ worldCount, lightCount] == null ){ if( material.ShaderName == "" || material.ShaderName == "basic"){ if( material.ShaderNameObj == null ){ material.ShaderNameObj = new BasicShaderName( worldCount, this.lightCount, material ); }else{ material.ShaderNameObj.SetWorldAndLight( worldCount, this.lightCount ); } program = shaderContainer.Find( material.ShaderNameObj ); material.BasicShader[ worldCount, lightCount] = program; }else{ // 特殊 program = shaderContainer.Find( material.ShaderName ); material.BasicShader[ worldCount, lightCount] = program; // uniform foreach( KeyValuePair< string, int > entry in material.BlindData ){ int id = program.FindUniform( entry.Key ); if( id >= 0 ){ program.SetUniformValue( id, entry.Value / 1000.0f ); } } } }else{ program = material.BasicShader[ worldCount, lightCount ]; } return program; }
/// Material::Layer の設定を Shader に作用する void setLayers( GraphicsContext graphics, BasicProgram program, BasicMaterial material ) { if( material.Layers == null ){ return ; } Texture texture = null ; int layerCount = (material.Layers.Length <= 3) ? material.Layers.Length : 3; program.SetTexCount( layerCount ); int texID = 0; if( NormalizeCubeMap != null ){ graphics.SetTexture( texID, NormalizeCubeMap ); texID++; } for( int i = 0; i < layerCount; i++ ){ BasicLayer layer = material.Layers[ i ]; texture = Textures[ layer.Texture ].Texture ; if( texture != null ){ // TexAnimation if( layer.TexAnimBoneIdx >= 0 ){ Vector3 st = new Vector3(); st.X = 1.0f - Bones[ layer.TexAnimBoneIdx ].Scaling.X; st.Y = 1.0f - Bones[ layer.TexAnimBoneIdx ].Scaling.Y; st.Z = 1.0f - Bones[ layer.TexAnimBoneIdx ].Scaling.Z; texAnims[ i ] = Matrix4.Transformation( Bones[ layer.TexAnimBoneIdx ].Translation + st, Bones[ layer.TexAnimBoneIdx ].Rotation, Bones[ layer.TexAnimBoneIdx ].Scaling ) ; }else{ texAnims[ i ] = Matrix4.Identity; } texture.SetWrap( (TextureWrapMode)layer.TexWrapU, (TextureWrapMode)layer.TexWrapV ); texture.SetFilter( (TextureFilterMode)layer.magFilter, (TextureFilterMode)layer.minFilter, (TextureFilterMode)layer.mipFilter ); // graphics.SetTexture( i + 1, texture ); graphics.SetTexture( texID, texture ); texID++; } program.SetTexMtx( texAnims ); program.SetTexCoord( i, material.Layers[ i ].TexCoord ); program.SetTangentID( material.Layers[ i ].TangentID ); program.SetTexType( i, material.Layers[ i ].TexType ); program.SetTexBlendFunc( i, material.Layers[ i ].TexBlendFunc ); } }
/// 指定 BasicProgram と、指定 BasicMaterial を必ず利用して描画する public void Draw( GraphicsContext graphics, BasicProgram program, BasicMaterial material, Matrix4 viewProj ) { List< LocalPart > localPartList = updateLocalPart(); // パーツを DrawOrder 順にソート localPartList.Sort(); setPolygonMode( graphics, material ); graphics.SetShaderProgram( program ); program.SetViewProj( viewProj ); program.SetMaterial( ref material ); setLayers( graphics, program, material ); // パーツの描画 foreach( LocalPart localPart in localPartList ){ program.SetMatrixPalette( localPart.worldCount, ref localPart.matrixPalette ); program.Update(); graphics.SetVertexBuffer( 0, localPart.vertexBuffer ) ; graphics.DrawArrays( localPart.primitives ) ; } }
public void SetMaterial( ref BasicMaterial material ) { if( idIKAmbient >= 0 ){ this.SetUniformValue( idIKAmbient, ref material.Ambient ); } if( idIDiffuse >= 0 ){ this.SetUniformValue( idIDiffuse, ref material.Diffuse ); } if( idISpecular >= 0 ){ this.SetUniformValue( idISpecular, ref material.Specular ); } if( idShininess >= 0 ){ this.SetUniformValue( idShininess, 80.8f ); } if( idAlphaThreshold >= 0 ){ this.SetUniformValue( idAlphaThreshold, material.AlphaThreshold ); } }
/// BasicMaterial に設定された ShaderName から、ShaderProgram を探して描画する public void Draw( GraphicsContext graphics, ShaderContainer shaderContainer, Matrix4 viewProj, Vector4 eye, float Brightness ) { foreach (var bone in Bones) { int worldCount = 0; // sky00_nami; // bone.Name = "sky00_nami"; int[] blendBones = bone.BlendBones; if (blendBones == null) { worldCount = 1; matrixBuffer = new Matrix4[1]; matrixBuffer[0] = bone.WorldMatrix; } else { int blendCount = blendBones.Length; if (blendCount > matrixBuffer.Length) { matrixBuffer = new Matrix4[blendCount]; } for (int i = 0; i < blendCount; i++) { matrixBuffer[i] = Bones[blendBones[i]].WorldMatrix * bone.BlendOffsets[i]; } } int[] blendSubset = defaultBlendSubset; foreach (var index in bone.DrawParts) { BasicPart part = Parts[index]; foreach (var mesh in part.Meshes) { if (blendBones != null && blendSubset != mesh.BlendSubset) { blendSubset = (mesh.BlendSubset != null) ? mesh.BlendSubset : defaultBlendSubset; worldCount = blendSubset.Length; if (worldCount > blendBones.Length) { worldCount = blendBones.Length; } } BasicMaterial material = Materials[mesh.Material]; if (material != null) { setPolygonMode(graphics, material); BasicProgram program = findBasicProgram(shaderContainer, material, worldCount, this.lightCount); graphics.SetShaderProgram(program); program.SetViewProj(viewProj); program.SetMaterial(ref material); if (material.LightEnable != 0) { program.SetLightCount(lightCount); program.SetLights(ref matrixBuffer[0], ref eye, ref lights); } else { program.SetLightCount(0); } program.SetRateLight(Brightness); setLayers(graphics, program, material); program.SetWorldCount(worldCount); for (int i = 0; i < worldCount; i++) { program.SetMatrixPalette(i, ref matrixBuffer[blendSubset[i]]); } program.Update(); } graphics.SetVertexBuffer(0, mesh.VertexBuffer); graphics.DrawArrays(mesh.Primitives); } } } }
void LoadMaterial( Chunk chunk, BasicMaterial material ) { int nLayers = CountChild( chunk, ChunkType.Layer ) ; material.Layers = new BasicLayer[ nLayers ] ; for ( int i = 0 ; i < nLayers ; i ++ ) material.Layers[ i ] = new BasicLayer() ; int iLayer = 0 ; material.Name = chunk.Name; Chunk child ; for ( int pos = chunk.Child ; pos < chunk.Next ; pos = child.Next ) { child = ReadChunk( pos ) ; int args = child.Args ; switch ( child.Type ) { case ChunkType.Layer : LoadLayer( child, chunk, material.Layers[ iLayer ++ ] ) ; break ; case ChunkType.Diffuse : // 変更 Vector3 -> Vector4 material.Diffuse = ReadVector4( args + 0 ) ; material.Opacity = ReadFloat( args + 12 ) ; break ; case ChunkType.Specular : // 変更 Vector3 -> Vector4 material.Specular = ReadVector4( args + 0 ) ; material.Shininess = ReadFloat( args + 16 ) ; break ; case ChunkType.Ambient : // 変更 Vector3 -> Vector4 material.Ambient = ReadVector4( args + 0 ) ; material.Opacity = ReadFloat( args + 12 ) ; break ; case ChunkType.Emission : // 変更 Vector3 -> Vector4 material.Emission = ReadVector4( args ) ; break ; case ChunkType.BlindData : ReadMaterialBlindData( material, child.Args, child.Args + child.ArgsSize ); break; } } }
/// Material::Layer の設定を Shader に作用する void setLayers( GraphicsContext graphics, BasicProgram program, BasicMaterial material ) { if (material.Layers == null) { return; } Texture texture = null; int layerCount = (material.Layers.Length <= 3) ? material.Layers.Length : 3; program.SetTexCount(layerCount); int texID = 0; if (NormalizeCubeMap != null) { graphics.SetTexture(texID, NormalizeCubeMap); texID++; } // bool flag = false; for (int i = 0; i < layerCount; i++) { BasicLayer layer = material.Layers[i]; // Console.WriteLine(layer.Texture); // layer.Texture = 5; /* * if(flag == false){ * layer.Texture = 0; * flag = true; * } */ texture = Textures[layer.Texture].Texture; // texture = Textures[ 1 ].Texture ; if (texture != null) { // TexAnimation if (layer.TexAnimBoneIdx >= 0) { Vector3 st = new Vector3(); st.X = 1.0f - Bones[layer.TexAnimBoneIdx].Scaling.X; st.Y = 1.0f - Bones[layer.TexAnimBoneIdx].Scaling.Y; st.Z = 1.0f - Bones[layer.TexAnimBoneIdx].Scaling.Z; texAnims[i] = Matrix4.Transformation(Bones[layer.TexAnimBoneIdx].Translation + st, Bones[layer.TexAnimBoneIdx].Rotation, Bones[layer.TexAnimBoneIdx].Scaling); } else { texAnims[i] = Matrix4.Identity; } texture.SetWrap((TextureWrapMode)layer.TexWrapU, (TextureWrapMode)layer.TexWrapV); texture.SetFilter((TextureFilterMode)layer.magFilter, (TextureFilterMode)layer.minFilter, (TextureFilterMode)layer.mipFilter); // graphics.SetTexture( i + 1, texture ); graphics.SetTexture(texID, texture); texID++; } program.SetTexMtx(texAnims); program.SetTexCoord(i, material.Layers[i].TexCoord); program.SetTangentID(material.Layers[i].TangentID); program.SetTexType(i, material.Layers[i].TexType); program.SetTexBlendFunc(i, material.Layers[i].TexBlendFunc); } }