/// <summary>
        /// Draw a mesh using either its given material or a transparent "ghost" material.
        /// </summary>
        /// <param name="node">Current node</param>
        /// <param name="animated">Specifies whether animations should be played</param>
        /// <param name="showGhost">Indicates whether to substitute the mesh' material with a
        /// "ghost" surrogate material that allows looking through the geometry.</param>
        /// <param name="index">Mesh index in the scene</param>
        /// <param name="mesh">Mesh instance</param>
        /// <param name="flags"> </param>
        /// <returns></returns>
        protected override bool InternDrawMesh(Node node, bool animated, bool showGhost, int index, Mesh mesh, RenderFlags flags)
        {
            if (showGhost)
            {
                Owner.MaterialMapper.ApplyGhostMaterial(mesh, Owner.Raw.Materials[mesh.MaterialIndex],
                                                        flags.HasFlag(RenderFlags.Shaded), flags.HasFlag(RenderFlags.ForceTwoSidedLighting));
            }
            else
            {
                Owner.MaterialMapper.ApplyMaterial(mesh, Owner.Raw.Materials[mesh.MaterialIndex],
                                                   flags.HasFlag(RenderFlags.Textured),
                                                   flags.HasFlag(RenderFlags.Shaded), flags.HasFlag(RenderFlags.ForceTwoSidedLighting));
            }

            if (GraphicsSettings.Default.BackFaceCulling)
            {
                GL.FrontFace(FrontFaceDirection.Ccw);
                GL.CullFace(CullFaceMode.Back);
                GL.Enable(EnableCap.CullFace);
            }
            else
            {
                GL.Disable(EnableCap.CullFace);
            }

            var hasColors    = mesh.HasVertexColors(0);
            var hasTexCoords = mesh.HasTextureCoords(0);

            var skinning = mesh.HasBones && animated;

            foreach (var face in mesh.Faces)
            {
                BeginMode faceMode;
                switch (face.IndexCount)
                {
                case 1:
                    faceMode = BeginMode.Points;
                    break;

                case 2:
                    faceMode = BeginMode.Lines;
                    break;

                case 3:
                    faceMode = BeginMode.Triangles;
                    break;

                default:
                    faceMode = BeginMode.Polygon;
                    break;
                }

                GL.Begin(faceMode);
                for (var i = 0; i < face.IndexCount; i++)
                {
                    var indice = face.Indices[i];
                    if (hasColors)
                    {
                        var vertColor = AssimpToOpenTk.FromColor(mesh.VertexColorChannels[0][indice]);
                        GL.Color4(vertColor);
                    }
                    if (mesh.HasNormals)
                    {
                        Vector3 normal;
                        if (skinning)
                        {
                            Skinner.GetTransformedVertexNormal(node, mesh, (uint)indice, out normal);
                        }
                        else
                        {
                            normal = AssimpToOpenTk.FromVector(mesh.Normals[indice]);
                        }

                        GL.Normal3(normal);
                    }
                    if (hasTexCoords)
                    {
                        var uvw = AssimpToOpenTk.FromVector(mesh.TextureCoordinateChannels[0][indice]);
                        GL.TexCoord2(uvw.X, 1 - uvw.Y);
                    }

                    Vector3 pos;
                    if (skinning)
                    {
                        Skinner.GetTransformedVertexPosition(node, mesh, (uint)indice, out pos);
                    }
                    else
                    {
                        pos = AssimpToOpenTk.FromVector(mesh.Vertices[indice]);
                    }
                    GL.Vertex3(pos);
                }
                GL.End();
            }
            GL.Disable(EnableCap.CullFace);
            return(skinning);
        }
Example #2
0
        public override void ApplyMaterial(Mesh mesh, Material mat, bool textured, bool shaded, bool twoSided)
        {
            RenderControl.GLError("StartMaterialMapper");
            ShaderGen.GenFlags flags = 0;
            var hasAlpha             = false;
            var hasTexture           = false;

            // note: keep this up-to-date with the code in MaterialMapper.UploadTextures()
            for (int i = 0; i < Renderer.modernGLUsedTextureTypeCount; i++)
            {
                TextureType currTextureType = (TextureType)((int)TextureType.Diffuse + i);
                GL.ActiveTexture((TextureUnit)((int)TextureUnit.Texture0 + i));
                GL.BindTexture(TextureTarget.Texture2D, Renderer.modernGLTextureType[i]); //we use own texture always, even when textures off to supply preset values
                if (textured && mat.GetMaterialTextureCount(currTextureType) > 0)
                {
                    hasTexture = true;
                    //flags |= ShaderGen.GenFlags.Texture; flag not used, we always have some texture
                    TextureSlot tex;
                    mat.GetMaterialTexture(currTextureType, 0, out tex);
                    var gtex = _scene.TextureSet.GetOriginalOrReplacement(tex.FilePath);
                    hasAlpha = hasAlpha || gtex.HasAlpha == Texture.AlphaState.HasAlpha;
                    if (gtex.State == Texture.TextureState.GlTextureCreated)
                    {
                        gtex.BindGlTexture();
                    }
                }
            }
            GL.ActiveTexture(TextureUnit.Texture0);
            RenderControl.GLError("EndTextureSettings");
            if (shaded)
            {
                flags |= ShaderGen.GenFlags.Lighting;
            }
            var hasColors = mesh != null && mesh.HasVertexColors(0);

            if (hasColors)
            {
                flags |= ShaderGen.GenFlags.VertexColor;
            }
            if (_UseSceneLights)
            {
                flags |= ShaderGen.GenFlags.PhongSpecularShading;
            }
            if ((mat.IsTwoSided) || (twoSided))
            {
                flags |= ShaderGen.GenFlags.TwoSide;
            }
            Shader shader = _shaderGen.GenerateOrGetFromCache(flags, _LightCount > 0 ? _LightCount : 1);

            shader.BindIfNecessary();
            Matrix4 curView = Matrix4.CreateScale(_scene.Scale) * _View;

            shader.SetMat4("WorldViewProjection", _World * curView * _Perspective);
            Matrix4 cameraPos      = _View.ClearRotation();
            Matrix4 cameraRotation = _View.ClearTranslation();
            Matrix4 cam            = Matrix4.Identity;

            cam = cameraPos * cameraRotation;
            Vector3 cameraPosition = -cam.ExtractTranslation() / _scene.Scale;//does not work for orbitcontroller

            //            cameraPosition = new Vector3(200,100,-100); //1m = 100units and positive
            cameraPosition.Z = -cameraPosition.Z;
            shader.SetVec3("CameraPosition", -cameraPosition);
            shader.SetMat4("World", _World);
            shader.SetMat4("WorldView", _World * curView); //_world* curView keeps light source at "fixed" position during rotating of the model
            shader.SetFloat("SceneBrightness", _SceneBrightness);
            shader.SetFloat("Material.diffuse", 0);
            shader.SetFloat("Material.ambient", 1);
            shader.SetFloat("Material.specular", 2);
            shader.SetFloat("Material.emissive", 3);
            shader.SetFloat("Material.height", 4);
            shader.SetFloat("Material.normal", 5);
            shader.SetLights(_GLLights, _LightCount);
            RenderControl.GLError("UniformSettings");

            // note: keep semantics of hasAlpha consistent with IsAlphaMaterial()
            var alpha = 1.0f;

            if (mat.HasOpacity)
            {
                alpha = mat.Opacity;
                if (alpha < AlphaSuppressionThreshold) // suppress zero opacity, this is likely wrong input data
                {
                    alpha = 1.0f;
                }
            }
            var color = new Color4(.8f, .8f, .8f, 1.0f);

            if (mat.HasColorDiffuse)
            {
                color = AssimpToOpenTk.FromColor(mat.ColorDiffuse);
                if (color.A < AlphaSuppressionThreshold) // s.a.
                {
                    color.A = 1.0f;
                }
            }
            color.A *= alpha;
            hasAlpha = hasAlpha || color.A < 1.0f;

            if (shaded)
            {
                // if the material has a texture but the diffuse color texture is all black,
                // then heuristically assume that this is an import/export flaw and substitute
                // white.
                if (hasTexture && color.R < 1e-3f && color.G < 1e-3f && color.B < 1e-3f)
                {
                    color = Color4.White;
                }
                shader.SetCol4("MaterialDiffuse_Alpha", color);

                color = new Color4(0, 0, 0, 1.0f);
                if (mat.HasColorSpecular)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorSpecular);
                }
                shader.SetCol4("MaterialSpecular", color);

                color = new Color4(.2f, .2f, .2f, 1.0f);
                if (mat.HasColorAmbient)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorAmbient);
                }
                shader.SetCol4("MaterialAmbient", color);

                color = new Color4(0, 0, 0, 1.0f);
                if (mat.HasColorEmissive)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorEmissive);
                }
                shader.SetCol4("MaterialEmissive", color);

                float shininess = 1;
                float strength  = 1;
                if (mat.HasShininess)
                {
                    shininess = mat.Shininess;
                }
                // todo: I don't even remember how shininess strength was supposed to be handled in assimp .. Scales the specular color of the material.Not implemented here.
                if (mat.HasShininessStrength)
                {
                    strength = mat.ShininessStrength;
                }
                var exp = shininess;
                if (exp >= 128.0f) // 128 is the maximum exponent as per the Gl spec
                {
                    exp = 128.0f;
                }
                shader.SetFloat("MaterialShininess", exp);
                //Shininess may be at mat.ColorSpecular.a too..?? but in FBX is
            }
            else if (!hasColors)
            {
                shader.SetCol4("MaterialDiffuse_Alpha", color);
            }

            if (hasAlpha)
            {
                GL.Enable(EnableCap.Blend);
                GL.BlendFuncSeparate(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha, BlendingFactorSrc.SrcAlpha, BlendingFactorDest.One);
                GL.DepthMask(false);
            }
            else
            {
                GL.DepthMask(true);
                GL.Disable(EnableCap.Blend);
            }
            RenderControl.GLError("EndMaterialMapper");
        }
        private void ApplyFixedFunctionMaterial(Mesh mesh, Material mat, bool textured, bool shaded)
        {
            shaded = shaded && (mesh == null || mesh.HasNormals);
            if (shaded)
            {
                GL.Enable(EnableCap.Lighting);
            }
            else
            {
                GL.Disable(EnableCap.Lighting);
            }

            var hasColors = mesh != null && mesh.HasVertexColors(0);

            if (hasColors)
            {
                GL.Enable(EnableCap.ColorMaterial);
                GL.ColorMaterial(MaterialFace.FrontAndBack, ColorMaterialParameter.AmbientAndDiffuse);
            }
            else
            {
                GL.Disable(EnableCap.ColorMaterial);
            }

            // note: keep semantics of hasAlpha consistent with IsAlphaMaterial()
            var hasAlpha   = false;
            var hasTexture = false;

            // note: keep this up-to-date with the code in UploadTextures()
            if (textured && mat.GetMaterialTextureCount(TextureType.Diffuse) > 0)
            {
                hasTexture = true;

                TextureSlot tex;
                mat.GetMaterialTexture(TextureType.Diffuse, 0, out tex);
                var gtex = _scene.TextureSet.GetOriginalOrReplacement(tex.FilePath);

                hasAlpha = hasAlpha || gtex.HasAlpha == Texture.AlphaState.HasAlpha;

                if (gtex.State == Texture.TextureState.GlTextureCreated)
                {
                    GL.ActiveTexture(TextureUnit.Texture0);
                    gtex.BindGlTexture();

                    GL.Enable(EnableCap.Texture2D);
                }
                else
                {
                    GL.Disable(EnableCap.Texture2D);
                }
            }
            else
            {
                GL.Disable(EnableCap.Texture2D);
            }

            GL.Enable(EnableCap.Normalize);

            var alpha = 1.0f;

            if (mat.HasOpacity)
            {
                alpha = mat.Opacity;
                if (alpha < AlphaSuppressionThreshold) // suppress zero opacity, this is likely wrong input data
                {
                    alpha = 1.0f;
                }
            }

            var color = new Color4(.8f, .8f, .8f, 1.0f);

            if (mat.HasColorDiffuse)
            {
                color = AssimpToOpenTk.FromColor(mat.ColorDiffuse);
                if (color.A < AlphaSuppressionThreshold) // s.a.
                {
                    color.A = 1.0f;
                }
            }
            color.A *= alpha;
            hasAlpha = hasAlpha || color.A < 1.0f;

            if (shaded)
            {
                // if the material has a texture but the diffuse color texture is all black,
                // then heuristically assume that this is an import/export flaw and substitute
                // white.
                if (hasTexture && color.R < 1e-3f && color.G < 1e-3f && color.B < 1e-3f)
                {
                    GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, Color4.White);
                }
                else
                {
                    GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, color);
                }

                color = new Color4(0, 0, 0, 1.0f);
                if (mat.HasColorSpecular)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorSpecular);
                }
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, color);

                color = new Color4(.2f, .2f, .2f, 1.0f);
                if (mat.HasColorAmbient)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorAmbient);
                }
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Ambient, color);

                color = new Color4(0, 0, 0, 1.0f);
                if (mat.HasColorEmissive)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorEmissive);
                }
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, color);

                float shininess = 1;
                float strength  = 1;
                if (mat.HasShininess)
                {
                    shininess = mat.Shininess;
                }
                // todo: I don't even remember how shininess strength was supposed to be handled in assimp
                if (mat.HasShininessStrength)
                {
                    strength = mat.ShininessStrength;
                }

                var exp = shininess * strength;
                if (exp >= 128.0f) // 128 is the maximum exponent as per the Gl spec
                {
                    exp = 128.0f;
                }

                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, exp);
            }
            else if (!hasColors)
            {
                GL.Color3(color.R, color.G, color.B);
            }

            if (hasAlpha)
            {
                GL.Enable(EnableCap.Blend);
                GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                GL.DepthMask(false);
            }
            else
            {
                GL.Disable(EnableCap.Blend);
                GL.DepthMask(true);
            }
        }
Example #4
0
        private void ApplyFixedFunctionMaterial(Mesh mesh, Material mat, bool textured, bool shaded)
        {
            shaded = shaded && (mesh == null || mesh.HasNormals);
            if (shaded)
            {
                GL.Enable(EnableCap.Lighting);
            }
            else
            {
                GL.Disable(EnableCap.Lighting);
            }

            var hasColors = mesh != null && mesh.HasVertexColors(0);

            if (hasColors)
            {
                GL.Enable(EnableCap.ColorMaterial);
                GL.ColorMaterial(MaterialFace.FrontAndBack, ColorMaterialParameter.AmbientAndDiffuse);
            }
            else
            {
                GL.Disable(EnableCap.ColorMaterial);
            }

            // note: keep semantics of hasAlpha consistent with IsAlphaMaterial()
            var hasAlpha   = false;
            var hasTexture = false;

            // note: keep this up-to-date with the code in UploadTextures()
            if (textured && mat.GetMaterialTextureCount(TextureType.Diffuse) > 0)
            {
                hasTexture = true;

                TextureSlot tex;
                mat.GetMaterialTexture(TextureType.Diffuse, 0, out tex);
                var gtex = _scene.TextureSet.GetOriginalOrReplacement(tex.FilePath);

                //hasAlpha = hasAlpha || gtex.HasAlpha == Texture.AlphaState.HasAlpha;
                hasAlpha = hasAlpha || mat.HasTextureOpacity;

                if (gtex.State == Texture.TextureState.GlTextureCreated)
                {
                    GL.ActiveTexture(TextureUnit.Texture0);
                    gtex.BindGlTexture();

                    GL.Enable(EnableCap.Texture2D);
                }
                else
                {
                    GL.Disable(EnableCap.Texture2D);
                }
            }
            else
            {
                GL.Disable(EnableCap.Texture2D);
            }

            GL.Enable(EnableCap.Normalize);

            var alpha = 1.0f;

            // Assimp always return true with obj/mtl
            // suppress zero opacity, this is likely wrong input data
            // But this may cause alpha 0.0f not working
            if (mat.HasOpacity && mat.Opacity > AlphaSuppressionThreshold && mat.Opacity != 1.0f)
            {
                alpha = mat.Opacity;
            }

            var    color = new Color4(.5f, .5f, .5f, 1.0f);
            Color4 c;

            if (mat.HasColorDiffuse && mat.Name != "DefaultMaterial")
            {
                color = AssimpToOpenTk.FromColor(mat.ColorDiffuse);
                if (color.A < AlphaSuppressionThreshold) // s.a.
                {
                    color.A = 1.0f;
                }
            }
            color.A *= alpha;
            hasAlpha = hasAlpha || color.A < 1.0f;

            if (shaded)
            {
                // if the material has a texture but the diffuse color texture is all black,
                // then heuristically assume that this is an import/export flaw and substitute
                // white.
                if (hasTexture && color.R < 1e-3f && color.G < 1e-3f && color.B < 1e-3f)
                {
                    GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, new Color4(1.0f, 1.0f, 1.0f, alpha));
                }
                else
                {
                    GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Diffuse, color);
                }


                //color = new Color4(0, 0, 0, 1.0f);
                //color = new Color4(1.0f, 1.0f, 1.0f, 1.0f);
                color = new Color4(0.5f, 0.5f, 0.5f, 1.0f);
                if (mat.HasColorSpecular && mat.Name != "DefaultMaterial")
                {
                    c = AssimpToOpenTk.FromColor(mat.ColorSpecular);
                    if (c.R + c.G + c.B > 0.0f)
                    {
                        color = c;
                    }
                }
                color.A *= alpha;
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Specular, color);

                // Assimp alaways returns HasColorAmbient with {0,0,0,1} when source file has no setting.
                // This makes ambient light becomes all black
                // (The same issue of diffuse color has been fixed above)
                // workaround: Shift color range from 1~0 to 1~(min ambient)
                float minAmb = 0.2f;
                color = new Color4(minAmb, minAmb, minAmb, 1.0f);
                //color = new Color4(.2f, .2f, .2f, 1.0f);
                if (mat.HasColorAmbient)
                {
                    color = AssimpToOpenTk.FromColor(mat.ColorAmbient);
                    float shiftC(float oc) => oc * (1.0f - minAmb) + minAmb;

                    color.R = shiftC(color.R);
                    color.G = shiftC(color.G);
                    color.B = shiftC(color.B);
                }
                color.A *= alpha;
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Ambient, color);

                color = new Color4(0, 0, 0, 1.0f);
                if (mat.HasColorEmissive)
                {
                    c = AssimpToOpenTk.FromColor(mat.ColorEmissive);
                    if (c.R + c.G + c.B > 0.0f)
                    {
                        color = c;
                    }
                }
                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Emission, color);

                // Assimp seems convert obj/mtl Ns value to Shininess and the strength value is not set
                float shininess = 1;
                float strength  = 1;
                if (mat.HasShininess && mat.Shininess > 0.0f)
                {
                    shininess = mat.Shininess;
                }
                // todo: I don't even remember how shininess strength was supposed to be handled in assimp
                if (mat.HasShininessStrength && mat.ShininessStrength > 0.0f)
                {
                    strength = mat.ShininessStrength;
                }

                var exp = shininess * strength;
                if (exp >= 128.0f) // 128 is the maximum exponent as per the Gl spec
                {
                    exp = 128.0f;
                }

                GL.Material(MaterialFace.FrontAndBack, MaterialParameter.Shininess, exp);
            }
            else if (!hasColors)
            {
                GL.Color3(color.R, color.G, color.B);
            }

            if (hasAlpha)
            {
                GL.Enable(EnableCap.Blend);
                GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha);
                GL.DepthMask(false);
            }
            else
            {
                GL.Disable(EnableCap.Blend);
                GL.DepthMask(true);
            }
        }