Help with shader

Irrlicht.Net is no longer developed or supported, Irrlicht.Net Cross Platform is a much more complete wrapper. Please ask your C# related questions on their forums first.
Locked
jingquan
Posts: 222
Joined: Sun Aug 20, 2006 4:10 am
Contact:

Help with shader

Post by jingquan »

Recently, I've been trying to convert this light shader: http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=21186 to C# and finally managed to compile it.

Here's a screenshot and there seems to be some major bug in it. It's suppose to be a normalmapped brick wall with 2 lights.

Image

And here's the source:

Code: Select all

using System;
using System.Text;
using IrrlichtNETCP;
using IrrlichtNETCP.Inheritable;
namespace LightShader
{
    public class lightshader
    {
        static string vertBumpShader = "uniform vec3 fvLightPosition1;" + "uniform vec3 fvLightPosition2;" + "uniform vec3 fvLightPosition3;" + "uniform vec3 fvLightPosition4;" + "" + "uniform float fLightStrength1;" + "uniform float fLightStrength2;" + "uniform float fLightStrength3;" + "uniform float fLightStrength4;" + "" + "uniform mat4 matWorldInverse;" + "" + "varying vec2 Texcoord;" + "varying vec3 ViewDirection;" + "varying vec3 LightDirection1;" + "varying vec3 LightDirection2;" + "varying vec3 LightDirection3;" + "varying vec3 LightDirection4;" + "varying vec4 LightDistMultiplier;" + "" + "float getLengthSQR (vec3 vec)" + "{" + "return(vec.x*vec.x+vec.y*vec.y+vec.z*vec.z);" + "}" + "" + "void main( void )" + "{" + "" + " mat4 LightTransform= gl_ModelViewMatrix;" + " LightTransform=LightTransform*matWorldInverse;" + "" + " gl_Position = ftransform();" + " Texcoord = gl_MultiTexCoord0.xy;" + "" + " vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;" + " vec4 fvLightPos1 = LightTransform * vec4(fvLightPosition1,1.0);" + " vec4 fvLightPos2 = LightTransform * vec4(fvLightPosition2,1.0);" + " vec4 fvLightPos3 = LightTransform * vec4(fvLightPosition3,1.0);" + " vec4 fvLightPos4 = LightTransform * vec4(fvLightPosition4,1.0);" + "" + " vec3 fvViewDirection = - fvObjectPosition.xyz;" + "" + " vec3 fvLightDirection1 = (fvLightPos1.xyz - fvObjectPosition.xyz);" + " vec3 fvLightDirection2 = (fvLightPos2.xyz - fvObjectPosition.xyz);" + " vec3 fvLightDirection3 = (fvLightPos3.xyz - fvObjectPosition.xyz);" + " vec3 fvLightDirection4 = (fvLightPos4.xyz - fvObjectPosition.xyz);" + "" + " LightDistMultiplier[0]=1.0/(getLengthSQR (fvLightDirection1)/(fLightStrength1*10000.0));" + " LightDistMultiplier[1]=1.0/(getLengthSQR (fvLightDirection2)/(fLightStrength2*10000.0));" + " LightDistMultiplier[2]=1.0/(getLengthSQR (fvLightDirection3)/(fLightStrength3*10000.0));" + " LightDistMultiplier[3]=1.0/(getLengthSQR (fvLightDirection4)/(fLightStrength4*10000.0));" + "" + " vec3 fvNormal = gl_NormalMatrix * gl_Normal;" + "" + " vec3 fvTangent = -vec3(abs(gl_Normal.y) + abs(gl_Normal.z), abs(gl_Normal.x), 0);" + " vec3 fvBinormal =cross(fvTangent,gl_Normal); " + " fvTangent=gl_NormalMatrix*cross(fvBinormal,gl_Normal);" + " fvBinormal=gl_NormalMatrix*fvBinormal;" + "" + "" + " ViewDirection.x = dot( fvTangent, fvViewDirection );" + " ViewDirection.y = dot( fvBinormal, fvViewDirection );" + " ViewDirection.z = dot( fvNormal, fvViewDirection );" + "" + " LightDirection1.x = dot( fvTangent, fvLightDirection1.xyz );" + " LightDirection1.y = dot( fvBinormal, fvLightDirection1.xyz );" + " LightDirection1.z = dot( fvNormal, fvLightDirection1.xyz );" + "" + " LightDirection2.x = dot( fvTangent, fvLightDirection2.xyz );" + " LightDirection2.y = dot( fvBinormal, fvLightDirection2.xyz );" + " LightDirection2.z = dot( fvNormal, fvLightDirection2.xyz );" + "" + " LightDirection3.x = dot( fvTangent, fvLightDirection3.xyz );" + " LightDirection3.y = dot( fvBinormal, fvLightDirection3.xyz );" + " LightDirection3.z = dot( fvNormal, fvLightDirection3.xyz );" + "" + " LightDirection4.x = dot( fvTangent, fvLightDirection4.xyz );" + " LightDirection4.y = dot( fvBinormal, fvLightDirection4.xyz );" + " LightDirection4.z = dot( fvNormal, fvLightDirection4.xyz );" + "" + "}";
        static string fragBumpShader = "uniform vec4 fvAmbient;" + "uniform vec4 fvLight1Color;" + "uniform vec4 fvLight2Color;" + "uniform vec4 fvLight3Color;" + "uniform vec4 fvLight4Color;" + "uniform float fSpecularPower;" + "uniform float fSpecularStrength;" + "uniform float fBumpStrength;" + "uniform sampler2D baseMap;" + "uniform sampler2D bumpMap;" + "uniform sampler2D strengthMap;" + "varying vec2 Texcoord;" + "varying vec3 ViewDirection;" + "varying vec3 LightDirection1;" + "varying vec3 LightDirection2;" + "varying vec3 LightDirection3;" + "varying vec3 LightDirection4;" + "varying vec4 LightDistMultiplier;" + "void main( void )" + "{" + " vec4 s=texture2D(strengthMap,Texcoord);" + " vec3 fvLightDirection1 = normalize( LightDirection1 );" + " vec3 fvLightDirection2 = normalize( LightDirection2 );" + " vec3 fvLightDirection3 = normalize( LightDirection3 );" + " vec3 fvLightDirection4 = normalize( LightDirection4 );" + " vec3 fvNormal = texture2D( bumpMap, Texcoord ).yxz;" + " fvNormal.xy*=2.0;" + " fvNormal.xy-=1.0;" + " fvNormal=(vec3(0.0,0.0,1.0)-fvNormal)*fBumpStrength*s.r+fvNormal;" + " fvNormal=normalize(fvNormal);" + " float fNDotL1 = max(dot(fvNormal, fvLightDirection1),0.0)-0.1; " + " float fNDotL2 = max(dot(fvNormal, fvLightDirection2),0.0)-0.1; " + " float fNDotL3 = max(dot(fvNormal, fvLightDirection3),0.0)-0.1; " + " float fNDotL4 = max(dot(fvNormal, fvLightDirection4),0.0)-0.1; " + " vec3 fvReflection1 = normalize( ( ( 2.0 * fvNormal ) ) - fvLightDirection1 ); " + " vec3 fvReflection2 = normalize( ( ( 2.0 * fvNormal ) ) - fvLightDirection2 ); " + " vec3 fvReflection3 = normalize( ( ( 2.0 * fvNormal ) ) - fvLightDirection3 ); " + " vec3 fvReflection4 = normalize( ( ( 2.0 * fvNormal ) ) - fvLightDirection4 ); " + " vec3 fvViewDirection = normalize( ViewDirection );" + " float fRDotV1 = max( 0.0, dot( fvReflection1, fvViewDirection ) );" + " float fRDotV2 = max( 0.0, dot( fvReflection2, fvViewDirection ) );" + " float fRDotV3 = max( 0.0, dot( fvReflection3, fvViewDirection ) );" + " float fRDotV4 = max( 0.0, dot( fvReflection4, fvViewDirection ) );" + " vec4 fvBaseColor = texture2D( baseMap, Texcoord );" + " vec4 fvTotalAmbient = fvAmbient * fvBaseColor; " + " vec4 fvTotalDiffuse = fvLight1Color * fNDotL1* fvBaseColor*LightDistMultiplier[0]; " + "float spec=fSpecularPower *s.b;" + " vec4 fvTotalSpecular = fNDotL1*fvLight1Color * ( pow( fRDotV1, spec ) )*LightDistMultiplier[0];" + " fvTotalDiffuse += fvLight2Color * fNDotL2* fvBaseColor*LightDistMultiplier[1]; " + " fvTotalSpecular += fNDotL2*fvLight2Color * ( pow( fRDotV2, spec ) )*LightDistMultiplier[1]; " + " fvTotalDiffuse += fvLight3Color * fNDotL3* fvBaseColor*LightDistMultiplier[2]; " + " fvTotalSpecular += fNDotL3*fvLight3Color * ( pow( fRDotV3, spec ) )*LightDistMultiplier[2]; " + " fvTotalDiffuse += fvLight4Color * fNDotL4* fvBaseColor*LightDistMultiplier[3]; " + " fvTotalSpecular += fNDotL4*fvLight4Color * ( pow( fRDotV4, spec ) )*LightDistMultiplier[3]; " + " vec4 color=( fvTotalAmbient + fvTotalDiffuse+ (fvTotalSpecular*fSpecularStrength*s.g));" + " if(color.r>1.0){color.gb+=color.r-1.0;}" + " if(color.g>1.0){color.rb+=color.g-1.0;}" + " if(color.b>1.0){color.rg+=color.b-1.0;}" + " gl_FragColor = color;" + "}";

        public class Shader_Bump_callback
        {
            public static float[] fLightStrength = new float[4];
            public static Vector3D[] fvLightPosition = new Vector3D[4];
            public static Colorf[] fvLightColor = new Colorf[4];
            public static Colorf fvAmbient;
            public static float fSpecularPower;
            public static float fSpecularStrength;
            public static float fBumpStrength;

            public static void OnShaderSet(MaterialRendererServices services, int userData)
            {
                int var0 = 0;
                services.SetPixelShaderConstant("baseMap", (float)var0);
                int var1 = 1;
                services.SetPixelShaderConstant("bumpMap", (float)var1);
                int var2 = 2;
                services.SetPixelShaderConstant("strengthMap", (float)var2); 
                Matrix4 invWorld = services.VideoDriver.GetTransform(TransformationState.World);
                invWorld.MakeInverse();
                services.SetPixelShaderConstant("matWorldInverse", invWorld.ToShader());
                services.SetPixelShaderConstant("fLightStrength1", fLightStrength[0]);
                services.SetPixelShaderConstant("fLightStrength2", fLightStrength[1]);
                services.SetPixelShaderConstant("fLightStrength3", fLightStrength[2]);
                services.SetPixelShaderConstant("fLightStrength4", fLightStrength[3]);
                services.SetPixelShaderConstant("fvLightPosition1", fvLightPosition[0].ToShader());
                services.SetPixelShaderConstant("fvLightPosition2", fvLightPosition[1].ToShader());
                services.SetPixelShaderConstant("fvLightPosition3", fvLightPosition[2].ToShader());
                services.SetPixelShaderConstant("fvLightPosition4", fvLightPosition[3].ToShader());
                services.SetPixelShaderConstant("fvAmbient", fvAmbient.ToShader());
                services.SetPixelShaderConstant("fvLight1Color", fvLightColor[0].ToShader());
                services.SetPixelShaderConstant("fvLight2Color", fvLightColor[1].ToShader());
                services.SetPixelShaderConstant("fvLight3Color", fvLightColor[2].ToShader());
                services.SetPixelShaderConstant("fvLight4Color", fvLightColor[3].ToShader());
                services.SetPixelShaderConstant("fSpecularPower", fSpecularPower);
                services.SetPixelShaderConstant("fSpecularStrength", fSpecularStrength);
                services.SetPixelShaderConstant("fBumpStrength", fBumpStrength);
            }
        }
        public static VideoDriver Driver;
        public static SceneManager Scene;

        public static void Main()
        {
            IrrlichtDevice device = new IrrlichtDevice(DriverType.OpenGL, new Dimension2D(1024, 768), 32, false, true, true, true);
            device.OnEvent += new OnEventDelegate(device_OnEvent);
            Driver = device.VideoDriver;
            Scene = device.SceneManager;
            GPUProgrammingServices gpu = Driver.GPUProgrammingServices;
            Shader_Bump_callback.fBumpStrength = 4;
            Shader_Bump_callback.fSpecularStrength = 0.9F;
            Shader_Bump_callback.fSpecularPower = 20;
            Shader_Bump_callback.fvAmbient = new Colorf(255, 2, 2, 2);
            Shader_Bump_callback.fLightStrength[0] = 1;
            Shader_Bump_callback.fvLightColor[0] = new Colorf(255, 100, 52, 31);
            Shader_Bump_callback.fvLightPosition[0] = new Vector3D(100, -10, 0);
            Shader_Bump_callback.fLightStrength[1] = 1;
            Shader_Bump_callback.fvLightColor[1] = new Colorf(255, 31, 55, 100);
            Shader_Bump_callback.fvLightPosition[1] = new Vector3D(-100, 10, 0);
            Material Mater = new Material();
            Mater.MaterialType = ((MaterialType)(gpu.AddHighLevelShaderMaterial(vertBumpShader, "main", VertexShaderType._1_1, fragBumpShader, "main", PixelShaderType._1_1, Shader_Bump_callback.OnShaderSet, MaterialType.Solid, 0)));
            CameraSceneNode fpsCamera = Scene.AddCameraSceneNodeFPS(null, 150, 250, false);
            fpsCamera.Position = new Vector3D(-90, 90, -90);
            device.CursorControl.Visible = false;
            AnimatedMesh mesh = Scene.GetMesh("alice_vg.3ds");
            SceneNode test = Scene.AddAnimatedMeshSceneNode(mesh);
            test.Position = new Vector3D(0, 0, 0);
            test.SetMaterialFlag(MaterialFlag.Lighting, false);
            test.SetMaterialTexture(0,Driver.GetTexture("alice_d.png"));
            test.SetMaterialTexture(1,Driver.GetTexture("alice_n.png"));
            test.SetMaterialTexture(3,Driver.GetTexture("alice_s.png"));
            test.GetMaterial(0).MaterialType = Mater.MaterialType;
            int lastFPS = -1;
            while (device.Run())
            {
                if (device.WindowActive)
                {
                    Driver.BeginScene(true, true, new Color(0, 0, 0, 0));
                    Driver.SetRenderTarget(null, true, true, new Color(0, 100, 100, 100));
                    Scene.DrawAll();
                    Driver.EndScene();
                    int fps = Driver.FPS;
                    if (!((lastFPS == fps)))
                    {
                        device.WindowCaption = "Shader Demo [" + fps + "]";
                        lastFPS = fps;
                    }
                }
            }
            device.Dispose();
        }

        static bool device_OnEvent(Event ev)
        {
            if (ev.KeyPressedDown && ev.KeyCode == KeyCode.Escape)
            {
                System.Environment.Exit(0);
            }
            return false;
        }
    }
}
I would really appericate if anyone could tell me what I had done wrong.
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Re: Help with shader

Post by Irme »

I haven't messed with the any of the shader stuff yet, but in comparison between the two sets of code, it looks like you have an extra texture added to your mesh. What happens when you don't add that third texture?

Code: Select all

            test.SetMaterialFlag(MaterialFlag.Lighting, false);
            test.SetMaterialTexture(0,Driver.GetTexture("alice_d.png"));
            test.SetMaterialTexture(1,Driver.GetTexture("alice_n.png"));
            test.SetMaterialTexture(3,Driver.GetTexture("alice_s.png"));
            test.GetMaterial(0).MaterialType = Mater.MaterialType;
jingquan
Posts: 222
Joined: Sun Aug 20, 2006 4:10 am
Contact:

Post by jingquan »

Oh that's a bug I've corrected by:

Code: Select all

            test.GetMaterial(0).Texture1 = Driver.GetTexture("alice_d.png");
            test.GetMaterial(0).Texture2 = Driver.GetTexture("alice_n.png");
            test.GetMaterial(0).Texture3 = Driver.GetTexture("alice_s.png");
            test.SetMaterialType(Mater);
That third texture is to be the specular map.

Still didn't work, it's all jumbled up colors.
jingquan
Posts: 222
Joined: Sun Aug 20, 2006 4:10 am
Contact:

Post by jingquan »

Now, the console says something about: fragment shader failed to link, but vertex succeed. What had i done wrong?
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Post by Irme »

I wish had some better suggestions for you, but maybe by using the .SetMaterialTexture and passing in the information, instead of using the .getmaterial and using = to assign the value in.

like this:

Code: Select all


test.SetMaterialTexture(0,Driver.GetTexture("alice_d.png"));
test.SetMaterialTexture(1,Driver.GetTexture("alice_n.png"));
test.SetMaterialTexture(2,Driver.GetTexture("alice_s.png")); 
test.SetMaterialType(Mater);

I'm grasping at straws - but give it a try.
jingquan
Posts: 222
Joined: Sun Aug 20, 2006 4:10 am
Contact:

Post by jingquan »

Oh wow, it's working now. Thanks a bunch.

Nows there's another problem: I want to use the shader on part of a mesh, but am forces to use .Texture1....and so on. Is there another way to assign texture on part of mesh without creating new material?
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Post by Irme »

The way i go around this, was just to create two different materials in memory, then depending on the situation i change the material between the two on the model.. i don't know if this is the most efficient way to do it. but it seems to be working.
jingquan
Posts: 222
Joined: Sun Aug 20, 2006 4:10 am
Contact:

Post by jingquan »

Could you explain in greater detail, I'l not sure how it's to be done. :?
Irme
Posts: 55
Joined: Sat Jul 16, 2005 8:24 am

Post by Irme »

Just declare two different materialtype variables globally, so they can be accessed elsewhere not just during your graphics init. Make one with the pretty shader stuff, and the other normal. Then based on some logical test, like if the mouse is over the node or whatever. Set the material type to one or the other materials.
jingquan
Posts: 222
Joined: Sun Aug 20, 2006 4:10 am
Contact:

Post by jingquan »

Oh, sorry for my bad explanation to my problem...

What I wanted was to load a second texture layer on part of a mesh (e.g. the map's lights and stuff) as the normalmap.

But creating a new material like this isn't possible:

Code: Select all

Material light = WorldNode.GetMaterial(0);
            light.SetMaterialTexture(1, driver.GetTexture("office/light_n.png"));
And I know I can't do this either:

Code: Select all

light.Texture2 = driver.GetTexture("office/light_n.png");
as the shader won't know it.

So the question is, how can I load a second texture on part of a mesh? Many thanks for your help.
Locked