Irrlicht to Pixel/Vertex Shader

If you are a new Irrlicht Engine user, and have a newbie-question, this is the forum for you. You may also post general programming questions here.
Post Reply
_Synthesizer
Posts: 9
Joined: Tue Nov 08, 2005 1:43 am

Irrlicht to Pixel/Vertex Shader

Post by _Synthesizer »

Hi,
I'm new to C++, Irrlicht, and shader programming, so bear with me :)

I am trying to make a HLSL shader, and for starters, I'm just going to be telling the shader what the light colour, position, and such are in the shader call back event (getting info from the lights will come later). My problem is that I am unsure about how to get the floats that I need for something like the colour to the shader. I have tried SColorf, and I got this error:
setPixelShaderConstant(const char *,const float *,int)' : cannot convert parameter 2 from 'class irr::video::SColorf *' to 'const float *

So I guess my question is: how do I make an array of the const float variety (or that may not be what I should be asking I suppose :P )
_Synthesizer
Posts: 9
Joined: Tue Nov 08, 2005 1:43 am

Post by _Synthesizer »

Never mind, I found the reinterpret_cast<f32*> function :)

Now, the next question is: what do I do to get the matViewProjection (I am creating my shader in RenderMonkey, actually, just tearing apart on of the included ones to see how they tick). Also what would the view_proj_martix be? I hope I'm right in guessing that the view_matrix is simply driver->getTransform(video::ETS_VIEW); and inv_view_matrix is the same with a makeInverse(); function.

Right now my shader makes a lovely coloured splatter appear instead of my object :P
_Synthesizer
Posts: 9
Joined: Tue Nov 08, 2005 1:43 am

Post by _Synthesizer »

Well, at this rate I'll have all my problems solved very quicky :P

I figured it out, and to those of you using RenderMonkey, swap your viewMatrix and position around, it helps quite a bit :wink:

Hmm, it works, but not how its supposed to. I believe that I am messing the info up from Irrlicht to the shader. For example, a specular highlight won't behave correctly and the lighting is incorrect. Maybe someone could help find what's wrong here, or maybe point me to some good tutorials.

--main.cpp--

class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:

virtual void OnSetConstants(video::IMaterialRendererServices* services)
{
video::IVideoDriver* driver = services->getVideoDriver();

//Setup for vertex-----------------------------------


//get the view matrix
core::matrix4 View = driver->getTransform(video::ETS_VIEW);
services->setVertexShaderConstant("view_matrix", &View.M[0], 16);

//get the view proj matrix
core::matrix4 viewProj;
viewProj = driver->getTransform(video::ETS_PROJECTION);
viewProj *= driver->getTransform(video::ETS_VIEW);
viewProj *= driver->getTransform(video::ETS_WORLD);

services->setVertexShaderConstant("view_proj_matrix", &viewProj.M[0], 16);


video::SColorf lightDir(0.5f,0.5f,0.5f,0.0f); //must be better way of storing a float4 for the shader
services->setVertexShaderConstant("lightDir", reinterpret_cast<f32*>(&lightDir), 4);

//Setup for Pixel--------------------------------------

//set lighting info (want to get from real light)
//Ambient
video::SColorf ambientC(0.7f,0.8f,1.0f,1.0f); //rbgw
irr::f32 ambientK = 0.3f; //ambient brightness
services->setPixelShaderConstant("ambient", reinterpret_cast<f32*>(&ambientC), 4); //send amb colour
services->setPixelShaderConstant("Ka", &ambientK, 1); //set amb power

//Diffuse
video::SColorf diffuseC(1.0f,0.9f,1.0f,0.85f); //rbgw
float diffuseK = 0.8f; //ambient brightness
services->setPixelShaderConstant("diffuse", reinterpret_cast<f32*>(&diffuseC), 4); //send diff colour
services->setPixelShaderConstant("Kd", &diffuseK, 1); //set diff power

//Spec
video::SColorf specC(1.0f,0.8f,0.7f,1.0f); //rbgw
float specK = 1.0; //spec brightness
services->setPixelShaderConstant("specular", reinterpret_cast<f32*>(&specC), 4); //send spec colour
services->setPixelShaderConstant("Ks", &specK, 1); //set spec power


//Spec Exponent
float specP2 = 20.0;
services->setPixelShaderConstant("n_specular", &specP2, 1); //set spec exp

}
};


--shader1_vs.hlsl--

float4x4 view_matrix;
float4x4 view_proj_matrix;
float4 lightDir;
struct VS_OUTPUT
{
float4 Pos : POSITION;
float3 Norm : TEXCOORD0;
float3 View : TEXCOORD1;
float3 Light : TEXCOORD2;
float2 Tex : TEXCOORD4;
};
VS_OUTPUT vertexMain(
float4 inPos : POSITION,
float3 inNorm : NORMAL,
float2 inTex : TEXCOORD0 )
{
VS_OUTPUT Out = (VS_OUTPUT) 0;

// Output transformed position:
Out.Pos = mul( inPos, view_proj_matrix );

// Output light vector:
Out.Light = -lightDir;

// Compute position in view space:
float3 Pview = mul( inPos, view_matrix);

// Transform the input normal to view space:
Out.Norm = normalize( mul( inNorm, view_matrix ) );

// Compute the view direction in view space:
Out.View = - normalize( Pview );

// Propagate texture coordinate for the object:
Out.Tex = inTex;

return Out;
}




--shader1_ps.hlsl--
float4 ambient;
float Ks;
float4 diffuse;
float Kd;
float4 specular;
float n_specular;
float Ka;
sampler baseMap;
float4 pixelMain( float4 Diff : COLOR0,
float3 Normal : TEXCOORD0,
float3 View : TEXCOORD1,
float3 Light : TEXCOORD2,
float2 Tex : TEXCOORD4 ) : COLOR
{
// Compute the reflection vector:
float3 vReflect = normalize( 2 * dot( Normal, Light) * Normal - Light );

// Compute ambient term:
float4 AmbientColor = ambient * Ka;

// Compute diffuse term:
float4 DiffuseColor = diffuse * Kd * max( 0, dot( Normal, Light ));

// Compute specular term:
float4 SpecularColor = specular * Ks * pow( max( 0, dot(vReflect, View)), n_specular );

float4 FinalColor = (AmbientColor + DiffuseColor) * tex2D( baseMap, Tex) + SpecularColor;

return FinalColor;
}
krama757
Posts: 451
Joined: Sun Nov 06, 2005 12:07 am

Post by krama757 »

Heh, thanks for the info.

Think you could include this in the wiki? For reference or tutorial purposes?
_Synthesizer
Posts: 9
Joined: Tue Nov 08, 2005 1:43 am

Post by _Synthesizer »

Hmm, I think it'd be more helpful if it actually worked before I added it :P I'm going to do a bit more digging around today, so hopefully I can figure it out.
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

its probablly due to the way u dont actually give the light dir??

maybe i cant see all the code
_Synthesizer
Posts: 9
Joined: Tue Nov 08, 2005 1:43 am

Post by _Synthesizer »

Hmm, it appears that the rotation animator I had on the cube the shader was on was messing stuff up. If I take that off, it appears to work normally :?

I'm taking a step backwards (where I should have started in the first place) and trying something simpiler to start with. Below is the code I have for the plastic shader from rendermonkey. What I am trying to do is get the light postion from Irrlicht to use in the shader. Getting it from the camera is fine, but I'm not quite sure of how to get it from the light. If you uncomment the rotate anim, you will see the problem that I'm getting. Also, replace my cube with your own geometry, or test scene node.


-------main.cpp---------

Code: Select all

//Include Main Header File
#include <irrlicht.h>

//Input Headers
#include <stdio.h>
#include <wchar.h>

//Setup Namespaces
using namespace irr;
using namespace core;
using namespace scene;
using namespace video;
using namespace io;
using namespace gui;

//Use irrlicht.dll
#pragma comment(lib, "Irrlicht.lib")

//Device Pointer
IrrlichtDevice* device = 0;
//Setup Esc = quit
class myEventReceiver : public IEventReceiver
{
public:
	virtual bool OnEvent(SEvent event)
	{
		if(event.EventType == EET_KEY_INPUT_EVENT && event.KeyInput.Key == KEY_ESCAPE && !event.KeyInput.PressedDown)
		{
			device->closeDevice();
		}return false;
	}
};

scene::ISceneNode* light1_node = 0;

//Shader Setup: Sends info to HLSL
class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:

   virtual void OnSetConstants(video::IMaterialRendererServices* services)
   {
      video::IVideoDriver* driver = services->getVideoDriver();
		//get the view proj matrix
      core::matrix4 viewProj;
      viewProj = driver->getTransform(video::ETS_PROJECTION);         
      viewProj *= driver->getTransform(video::ETS_VIEW);
	  viewProj *= driver->getTransform(video::ETS_WORLD);

         services->setVertexShaderConstant("view_proj_matrix", &viewProj.M[0], 16);

         //Use the camera to get the view position
		core::vector3df viewPos = device->getSceneManager()->
         getActiveCamera()->getAbsolutePosition();

	  services->setVertexShaderConstant("view_position", reinterpret_cast<f32*>(&viewPos), 4);

	  //colour of the object
	  SColorf col1(1.0f, 0.89f, 0.75f, 1.0f);
	services->setPixelShaderConstant("color", reinterpret_cast<f32*>(&col1), 4);
   }
};
	

//Start
int main()
{
    
myEventReceiver receiver;
//Create Irr Device                                                  resolution, bit depth, fullscreen, stencil buffer, vsync
device = createDevice(EDT_DIRECTX9, dimension2d<s32>(800, 600), 32, false, true, false, &receiver);

//Window Caption
device->setWindowCaption(L"Materials Tests");

//General Pointers
IVideoDriver* driver = device->getVideoDriver();
ISceneManager* smgr = device->getSceneManager();
IGUIEnvironment* guienv = device->getGUIEnvironment();


//Create material
   video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
   s32 newMaterialType1 = 0;

   //Do callback
   if (gpu)
   {
      MyShaderCallBack* mc = new MyShaderCallBack();

         // create material from high level shaders

         newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
            "shaders/shader3_vs.hlsl",   "vertexMain", video::EVST_VS_1_1,
            "shaders/shader3_ps.hlsl", "pixelMain", video::EPST_PS_2_0,
            mc, video::EMT_SOLID);

		 mc->drop();
   }

//Add spinning cube (not spinning anymore)
IAnimatedMesh* cube1_mesh = smgr->getMesh("./models/cube1.obj");

IAnimatedMeshSceneNode* cube1_node = smgr->addAnimatedMeshSceneNode(cube1_mesh);
cube1_node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);
cube1_node->setMaterialFlag(EMF_TRILINEAR_FILTER, true);


/*
	ISceneNodeAnimator* cube1_anim = smgr->createRotationAnimator(
			core::vector3df(0,0.5f,0));
	cube1_node->addAnimator(cube1_anim);
	cube1_anim->drop();
*/

//Create a FPS camera
ICameraSceneNode* camera1_node = 	
		camera1_node = smgr->addCameraSceneNodeFPS(0,120.0f,250.0f);  //parent,rotate,move
	camera1_node->setPosition(core::vector3df(0,20,65));

// disable mouse cursor
	device->getCursorControl()->setVisible(false);

//light1 Scene Node
scene::ISceneNode* light1_node = smgr->addLightSceneNode(0, core::vector3df(100,200,100), 
		video::SColorf(0.8f, 0.75f, 0.7f, 1.0f), 900.0f);


//Run everything
while(device->run()){
    
    //Start by clearing with a colour
    driver->beginScene(true, true, SColor(0,160,160,160));
    
    smgr->drawAll();
    guienv->drawAll();
    
    driver->endScene();
}

//Drop the IrrDevice on exit
device->drop();

return 0;
}    
------------shader3_vs.hlsl------------

Code: Select all

float4x4 view_proj_matrix: register(c0);
float4 view_position: register(c4);
struct VS_OUTPUT {
   float4 Pos:     POSITION;
   float3 normal:  TEXCOORD0;
   float3 viewVec: TEXCOORD1;
};

VS_OUTPUT vertexMain(float4 Pos: POSITION, float3 normal: NORMAL){
   VS_OUTPUT Out;

   Out.Pos = mul( Pos, view_proj_matrix ); //remember to flip from rendermonkey

   // View-space lighting
   Out.normal = normal;
   Out.viewVec = view_position - Pos;

   return Out;
}
-----------shader3_ps.hlsl-------------

Code: Select all

float4 color:register(c0);

float4 pixelMain(float3 normal: TEXCOORD0, float3 viewVec: TEXCOORD1) : COLOR {
   	// Simple lighting lighting model for a dull plastic appearance.
   	float v = 0.5 * (1 + dot(normalize(viewVec), normal));

   	return v * color;

}
_Synthesizer
Posts: 9
Joined: Tue Nov 08, 2005 1:43 am

Post by _Synthesizer »

Whee! I finally got things figured out. I highly recommend anyone learning about HLSL to check out this page: http://www.gamasutra.com/features/20030 ... el_pfv.htm

It helped me out a huge amount. I've worked my way to the specular section, tomorrow I'll check out bumpmapping :D
Guest

Post by Guest »

Nice work! I'm learning HLSL and GLSL as well using RenderMonkey for script testing. And I agree with krama757, this would be good material for the wiki, if you've got the inclination to add it... :wink:
Guest

Post by Guest »

Yes, I think I will add something when I've got a bit more figured out. A shader that is actually useful would be a big help for those trying to learn it, it would have helped me alot :P
_Synthesizer
Posts: 9
Joined: Tue Nov 08, 2005 1:43 am

Post by _Synthesizer »

And that Guest was me :roll:
Post Reply