Page 1 of 1

Help with shader

Posted: Tue Jun 19, 2007 2:16 am
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.

Re: Help with shader

Posted: Tue Jun 19, 2007 4:26 pm
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;

Posted: Wed Jun 20, 2007 1:30 am
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.

Posted: Wed Jun 20, 2007 10:26 am
by jingquan
Now, the console says something about: fragment shader failed to link, but vertex succeed. What had i done wrong?

Posted: Wed Jun 20, 2007 4:09 pm
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.

Posted: Mon Jun 25, 2007 10:22 am
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?

Posted: Mon Jun 25, 2007 8:28 pm
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.

Posted: Tue Jun 26, 2007 12:16 pm
by jingquan
Could you explain in greater detail, I'l not sure how it's to be done. :?

Posted: Tue Jun 26, 2007 2:23 pm
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.

Posted: Wed Jun 27, 2007 8:28 am
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.