Problems with a my shader.....

You are an experienced programmer and have a problem with the engine, shaders, or advanced effects? Here you'll get answers.
No questions about C++ programming or topics which are answered in the tutorials!
Post Reply
Gulovek
Posts: 6
Joined: Wed Jul 04, 2007 3:41 pm

Problems with a my shader.....

Post by Gulovek »

hi all. ( again sorry about my bad english )
after playing arround with irrlicht for a while i started to implement my shaders to irrlicht. so i wanted to convert from my old dx9 project a hlsl shader to irrlicht. after reading the shader tutorial and some post on the forum i started to implement my hlsl shader and failed.
screen shows nothing. :(
i have tested the code without a shader class just to look that everthing shows up on the screen and its working.

i show you parts of my code what i have done so far.
( code seems abit broken in the format . sorry for that )

first the shader class i have implement from the tutorial.
dont wonder about the const instructions. its just for testing.

Code: Select all

class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
	public:
	
	virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
	{
		// some testvalues for the shader
		const float	lightPosition[]		= { 100.0f,100.0f,100.0f,0.0f };
		const float	lightColor[]		= { 1.0f,1.0f,1.0f,1.0f };
		const float	lightAmbient[]		= { 1.0f,1.0f,1.0f,1.0f };
		const float	materialSpecular[]	= { 1.0f,1.0f,1.0f,1.0f };
		float shininess	= 128.0f;

		video::IVideoDriver* driver = services->getVideoDriver();

		// set clip matrix
		core::matrix4 model;
		core::matrix4 modelviewproj;
		core::matrix4 modelview;
		core::matrix4 view;
		core::matrix4 proj;

		model = driver->getTransform(video::ETS_WORLD);
		view = driver->getTransform(video::ETS_VIEW);
		proj = driver->getTransform(video::ETS_PROJECTION);			

		modelviewproj = ( model * view ) * proj ;
		modelview = model * view;
		
		// set vertexshader values
		services->setVertexShaderConstant("modelviewproj",			&modelviewproj.M[0]			,16);
		services->setVertexShaderConstant("modelview",				&modelview.M[0]				,16);
		services->setVertexShaderConstant("view",					&view.M[0]					,16);
		services->setVertexShaderConstant("lightPosition",			&lightPosition[0]			, 4);
		// set pixelshader values
		services->setPixelShaderConstant("lightColor",				&lightColor[0]			, 4);
		services->setPixelShaderConstant("lightAmbient",			&lightAmbient[0]		, 4);
		services->setPixelShaderConstant("materialSpecular",		&materialSpecular[0]	, 4);
		services->setPixelShaderConstant("shininess",				&shininess				, 1);
	}
};
parts of the main code that use the shader...

Code: Select all

	psFileName = "media/perpixelspec.hlsl";
	vsFileName = psFileName; // both shaders are in the same file
	
	video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
	s32 newMaterialType1 = 0;
	if ( gpu )
	{
		MyShaderCallBack* mc = new MyShaderCallBack();
		newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
					vsFileName,	"view_space", video::EVST_VS_1_1,
					psFileName, "normal_map", video::EPST_PS_2_0,
					mc, video::EMT_NORMAL_MAP_SOLID);

		mc->drop();
	}

	// node of the bsp file 
	scene::ISceneNode* node = 0;
	irr::core::stringc textureName;
	irr::core::stringc textureName2;
	
	// convert the mesh to tangent binormal mesh
	if ( mesh )
	{
		scene::IMesh* tangentMesh = smgr->getMeshManipulator()->createMeshWithTangents(
			mesh->getMesh(0));
		node = smgr->addMeshSceneNode ( tangentMesh );

		for ( int iMatCount = 0; iMatCount<node->getMaterialCount(); iMatCount++ )
		{
			textureName = node->getMaterial(iMatCount).Textures[0]->getName();
			textureName2 = textureName.subString(0,textureName.size()-4)+"_normal.tga";
			node->getMaterial(iMatCount).Textures[1] = driver->getTexture(textureName2.c_str());
			node->getMaterial(iMatCount).MaterialType = (video::E_MATERIAL_TYPE)newMaterialType1;
		}
		tangentMesh->drop();
	}
here ist the hlsl shader code i use...

Code: Select all

//------------------------------------
float4x4 modelviewproj;
float4x4 modelview;	
float4x4 view;			

float4 lightPosition;
float4 lightColor;
float4 lightAmbient;
float4 materialSpecular;
float  shininess;

sampler diffuseTexture 			: register(s0);
sampler normalTexture 			: register(s1);

struct a2v 
{
    float4 pos					: POSITION;
    float3 normal				: NORMAL;
    float4 color				: COLOR0;
    float2 txcoord				: TEXCOORD0;
    float3 tangent				: TANGENT0;
    float3 binormal				: BINORMAL0;
};

struct v2f
{
    float4 hpos					: POSITION;
    float2 txcoord				: TEXCOORD0;
    float3 vpos					: TEXCOORD1;
    float3 tangent				: TEXCOORD2;
    float3 binormal				: TEXCOORD3;
    float3 normal				: TEXCOORD4;
	float3 viewVector			: TEXCOORD5;		
	float3 lightVector			: TEXCOORD6;	
};

v2f view_space(a2v IN)
{
	v2f OUT;

	// vertex position in object space
	float4 pos=float4(IN.pos.x,IN.pos.y,IN.pos.z,1.0);

	// compute modelview rotation only part
	float3x3 modelviewrot;
	modelviewrot[0]=modelview[0].xyz;
	modelviewrot[1]=modelview[1].xyz;
	modelviewrot[2]=modelview[2].xyz;

	// vertex position in clip space
	OUT.hpos=mul(pos,modelviewproj);

	// vertex position in view space (with model transformations)
	OUT.vpos=mul(pos,modelview).xyz;

	// light position in view space
	float4 lp=mul(lightPosition,view);

	// view and light directions
	OUT.viewVector = normalize(OUT.vpos);
	OUT.lightVector = normalize(lp.xyz-OUT.vpos);
	
	// tangent space vectors in view space (with model transformations)
	OUT.tangent=mul(IN.tangent,modelviewrot);
	OUT.binormal=mul(IN.binormal,modelviewrot);
	OUT.normal=mul(IN.normal,modelviewrot);
	
	// copy texture coordinates
	OUT.txcoord=IN.txcoord.xy;

	return OUT;
}

float4 normal_map( v2f IN, uniform sampler2D diffuseTexture, uniform sampler2D normalTexture) : COLOR
{
	float4 normal=tex2D(normalTexture,IN.txcoord);
	normal.xy=normal.xy*2.0-1.0; // trafsform to [-1,1] range
	normal.z=sqrt(1.0-dot(normal.xy,normal.xy)); // compute z component
	
	// transform normal to world space
	normal.xyz=normalize(normal.x*IN.tangent-normal.y*IN.binormal+normal.z*IN.normal);
	
	// color map
	float4 color=tex2D(diffuseTexture,IN.txcoord);
	
	// compute diffuse and specular 
	float att=saturate(dot(IN.lightVector,IN.normal.xyz));
	float diff=saturate(dot(IN.lightVector,normal.xyz));
	float spec=saturate(dot(normalize(IN.lightVector-IN.viewVector),normal.xyz));

	// compute final color
	float4 finalcolor;
	finalcolor.xyz=lightAmbient*color.xyz+
		att*(color.xyz*lightColor.xyz*diff+materialSpecular.xyz*pow(spec,shininess));

	finalcolor.w=1.0;
	return finalcolor;
}
there is one thing iam not sure if this is correct in the shader.
the input stream of the vertices.

Code: Select all

struct a2v 
{
    float4 pos					: POSITION;
    float3 normal				: NORMAL;
    float4 color				: COLOR0;
    float2 txcoord				: TEXCOORD0;
    float3 tangent				: TANGENT0;
    float3 binormal				: BINORMAL0;
};
when i use smgr->getMeshManipulator()->createMeshWithTangents(..)
i get the S3DVertexTangents format.
but iam not sure if the order of the vertex information is the same as i
declared in my shader input stream.

any help would be nice if i have missed something or have done wrong.
the shader itself works on my old dx9 project.
Luben
Posts: 568
Joined: Sun Oct 09, 2005 10:12 am
Location: #irrlicht @freenode

Post by Luben »

I'm not sure if this solves your problem, btu i noticed you multiply your matrices in the callback in the order we say worldviewproj, but i'm pretty sure they are supposed to be multiplied in the reversed order, ie. projviewworld. Here's a part of the shader tutorial

Code: Select all

		core::matrix4 worldViewProj;
		worldViewProj = driver->getTransform(video::ETS_PROJECTION);			
		worldViewProj *= driver->getTransform(video::ETS_VIEW);
		worldViewProj *= driver->getTransform(video::ETS_WORLD);
Hope that solves it.
If you don't have anything nice to say, don't say anything at all.
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

the vertex stream is invalid for irrlicht since the tangents and bionormal use texcoords 1 and 2.

As for seeing nothing the transform maybe wrong because of the reason luben stated.
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
Gulovek
Posts: 6
Joined: Wed Jul 04, 2007 3:41 pm

Post by Gulovek »

it doesent work. well i forget to tell that the mesh i use and convert to tangent mesh is a loaded quake3 bsp map.

better i show the whole code...

Code: Select all

#include "stdafx.h"
#include <irrlicht.h>
#include <iostream>

using namespace irr;
using namespace scene;

#pragma comment(lib, "Irrlicht.lib")

IrrlichtDevice* device = 0;
bool UseHighLevelShaders = false;

class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
	public:
	
	virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
	{
		// some testvalues for the shader
		const float	lightPosition[]		= { -100.0f,100.0f,100.0f,0.0f };
		const float	lightColor[]		= { 0.4f,0.4f,0.4f,1.0f };
		const float	lightAmbient[]		= { 0.4f,0.4f,0.4f,1.0f };
		const float	materialSpecular[]	= { 0.4f,0.4f,0.4f,1.0f };
		float shininess	= 32.0f;

		video::IVideoDriver* driver = services->getVideoDriver();

		// set clip matrix
		core::matrix4 model;
		core::matrix4 modelview;
		core::matrix4 view;
		core::matrix4 proj;

		model = driver->getTransform(video::ETS_WORLD);
		view = driver->getTransform(video::ETS_VIEW);
	
		core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
	 	worldViewProj *= driver->getTransform(video::ETS_VIEW);
	 	worldViewProj *= driver->getTransform(video::ETS_WORLD);

		modelview = view * model;
		
		// set vertexshader values
		services->setVertexShaderConstant("modelviewproj",			worldViewProj.pointer() ,16);
		services->setVertexShaderConstant("modelview",				modelview.pointer()		,16);
		services->setVertexShaderConstant("view",					view.pointer()			,16);
		services->setVertexShaderConstant("lightPosition",			&lightPosition[0]		, 4);
		// set pixelshader values
		services->setPixelShaderConstant("lightColor",				&lightColor[0]			, 4);
		services->setPixelShaderConstant("lightAmbient",			&lightAmbient[0]		, 4);
		services->setPixelShaderConstant("materialSpecular",		&materialSpecular[0]	, 4);
		services->setPixelShaderConstant("shininess",				&shininess				, 1);
	}
};
int IRRCALLCONV main(int argc, char* argv[])
{
	// Video driver select
	bool bFullScreen = false;
		video::E_DRIVER_TYPE driverType;

	printf("Please select the driver you want for this example:\n"\
		" (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\
		" (d) Software Renderer\n (e) Burning's Software Renderer\n"\
		" (f) NullDevice\n (otherKey) exit\n\n");

	char i;
	std::cin >> i;

	switch(i)
	{
		case 'a': driverType = video::EDT_DIRECT3D9;break;
		case 'b': driverType = video::EDT_DIRECT3D8;break;
		case 'c': driverType = video::EDT_OPENGL;   break;
		case 'd': driverType = video::EDT_SOFTWARE; break;
		case 'e': driverType = video::EDT_BURNINGSVIDEO;break;
		case 'f': driverType = video::EDT_NULL;     break;
		default: return 1;
	}	

	printf("FullScreen ?\n");

	std::cin >> i;

	switch(i)
	{
		case 'y': bFullScreen = true;break;
		case 'n': bFullScreen = false;;break;
		default: return 1;
	}	
	
	int iWidth, iHeight;

	if ( bFullScreen )
	{
		iWidth = 1280; iHeight = 1024;
	}
	else
	{
		iWidth = 1024; iHeight = 768;
	}
	
	core::dimension2di videoDim ( iWidth,iHeight );
	device = createDevice(driverType, videoDim, 32, bFullScreen, true, false );

	if (device == 0)
		return 1; // could not create selected driver.

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	
	// set media path and add zip pk3 file
	device->getFileSystem()->addFolderFileArchive("media/");
	device->getFileSystem()->addZipFileArchive("media/first.pk3");
	
	// load a bsp map
	scene::IQ3LevelMesh* mesh = (scene::IQ3LevelMesh*) smgr->getMesh("maps/test5.bsp");
	// load hlsl shader
	c8* vsFileName = 0; // filename for the vertex shader
	c8* psFileName = 0; // filename for the pixel shader
	
	psFileName = "media/perpixelspec.hlsl";
	vsFileName = psFileName; // both shaders are in the same file
	
	video::IGPUProgrammingServices* gpu = driver->getGPUProgrammingServices();
	s32 newMaterialType1 = 0;
	if ( gpu )
	{
		MyShaderCallBack* mc = new MyShaderCallBack();
		newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
					vsFileName,	"vshader", video::EVST_VS_1_1,
					psFileName, "pshader", video::EPST_PS_2_0,
					mc, video::EMT_NORMAL_MAP_SOLID);

		mc->drop();
	}

	// node of the bsp file 
	scene::ISceneNode* node = 0;
	
	irr::core::stringc textureName;
	irr::core::stringc textureName2;
	
	// convert the mesh to tangent binormal mesh
	if ( mesh )
	{
		scene::IMesh* tangentMesh = smgr->getMeshManipulator()->createMeshWithTangents(mesh->getMesh(0));
		node = smgr->addMeshSceneNode ( tangentMesh );

		for ( int iMatCount = 0; iMatCount<node->getMaterialCount(); iMatCount++ )
		{
			textureName = node->getMaterial(iMatCount).Textures[0]->getName();
			textureName2 = textureName.subString(0,textureName.size()-4)+"_normal.tga";
			node->getMaterial(iMatCount).Textures[1] = driver->getTexture(textureName2.c_str());
			node->getMaterial(iMatCount).MaterialType = (video::E_MATERIAL_TYPE)newMaterialType1;
		}
	}

	// create a triangle selector for collision detection
	scene::ITriangleSelector* selector = 0;
	if (node)
	{		
		selector = smgr->createOctTreeTriangleSelector(mesh->getMesh(0), node, 128);
		node->setTriangleSelector(selector);
		selector->drop();
	}
	
	// release the mesh since its not longer needed
	if ( mesh )
	{
		// original mesh is not needed anymore
		mesh->releaseMesh ( quake3::E_Q3_MESH_ITEMS );
	}
	
	// add a fps camera to the scene
	scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS();
	
	// get starting postion from the mesh entity list
	if ( mesh )
	{
		const quake3::tQ3EntityList &entityList = mesh->getEntityList ();

		quake3::SEntity search;
		search.name = "info_player_deathmatch";

		s32 index = entityList.binary_search_const ( search );
		if ( index >= 0 )
		{
			const quake3::SVarGroup *group;
			s32 notEndList;
			do
			{
				group = entityList[ index ].getGroup(1);

				u32 parsepos = 0;
				core::vector3df pos = quake3::getAsVector3df ( group->get ( "origin" ), parsepos );

				parsepos = 0;
				f32 angle = quake3::getAsFloat ( group->get ( "angle"), parsepos );

				core::vector3df target ( 0,0,1 );
				target.rotateXZBy ( angle, core::vector3df () );

				camera->setPosition ( pos );
				camera->setTarget ( pos + target );

				index += 1;
				notEndList = (	index < (s32) entityList.size () &&
								entityList[index].name == search.name &&
								(device->getTimer()->getRealTime() >> 3 ) & 1
							);

			} while ( notEndList );
		}
	}
	
	// create a collision respond animation
	scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
		selector, camera, core::vector3df(30,50,30),
		core::vector3df(0,-3,0),
		core::vector3df(0,20,0));
	camera->addAnimator(anim);
	anim->drop();
	
	// disable mousecursor
	device->getCursorControl()->setVisible(false);
	
	int lastFPS = -1;
	
	// draw the scene
	while(device->run())
	if (device->isWindowActive())
	{
		driver->beginScene(true, true, video::SColor(255,20,20,40));

		smgr->drawAll();

		driver->endScene();
		
		// save fps information
		int fps = driver->getFPS();
		if (lastFPS != fps)
		{
			io::IAttributes * attr = smgr->getParameters();

			s32 calls = attr->getAttributeAsInt ( "calls" );
			s32 culled = attr->getAttributeAsInt ( "culled" );

			core::stringw str = L"Q3 [";
			str += driver->getName();
			str += "] FPS:";
			str += fps;
			str += " Cull:";
			str += calls;
			str += "/";
			str += culled;

			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
	}
	device->drop();
	return 0;
}
i have tested the code without a shader and the quake map shows just fine. when the hlsl shader running the screen is empty.

what i really thinking that it has something to do with the generated vertices when using createMeshWithTangents.
when i look into file: x:\irrlicht-1.3.1\source\Irrlicht\CD3D9Driver.cpp
i found at line 1141....

Code: Select all

//! sets right vertex shader
void CD3D9Driver::setVertexShader(E_VERTEX_TYPE newType)
{
	if (newType != LastVertexType)
	{
		LastVertexType = newType;
		HRESULT hr = 0;

		switch(newType)
		{
		case EVT_STANDARD:
			hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1);
			break;
		case EVT_2TCOORDS:
			hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX2);
			break;
		case EVT_TANGENTS:
			hr = pID3DDevice->SetFVF(D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX3 |
				D3DFVF_TEXCOORDSIZE2(0) | // real texture coord
				D3DFVF_TEXCOORDSIZE3(1) | // misuse texture coord 2 for tangent
				D3DFVF_TEXCOORDSIZE3(2)   // misuse texture coord 3 for binormal
				);
			break;
		}

		if (FAILED(hr))
		{
			os::Printer::log("Could not set vertex Shader.", ELL_ERROR);
			return;
		}
	}
}
as you can see i tried to have the same vertex definition in my hlsl shader for the vertex input..

Code: Select all

struct a2v 
{
    float4 pos					: POSITION;
    float3 normal				: NORMAL;
    float4 color				: COLOR0;
    float2 txcoord				: TEXCOORD0;
    float3 tangent				: TANGENT0;
    float3 binormal				: BINORMAL0;
};
ofcourse my struct in the hlsl shader ist not correct or in the same order with the vertices that was created with createMeshWithTangents ?

thanks again fpr any reply.
Gulovek
Posts: 6
Joined: Wed Jul 04, 2007 3:41 pm

Post by Gulovek »

i change things like luben said and i have also change the vertex stream
like you said:

Code: Select all

struct a2v 
{
    float4 pos					: POSITION;
    float3 normal				: NORMAL;
    float4 color				: COLOR0;
    float2 txcoord				: TEXCOORD0;
    float3 tangent				: TEXCOORD1;
    float3 binormal				: TEXCOORD2;
};
still no luck.
BlindSide
Admin
Posts: 2821
Joined: Thu Dec 08, 2005 9:09 am
Location: NZ!

Post by BlindSide »

Sorry I tried to look but I cant find in the thread anywhere if you have mentioned whether there are any shader errors in the console or not.
Gulovek
Posts: 6
Joined: Wed Jul 04, 2007 3:41 pm

Post by Gulovek »

nope no error for the shader in the console.
i tested the shader in dx project without irrlicht and it works just fine.
but i will try again on weekend and test with some simply irrlicht projects and simply shaders to look if it works.

thanks for your reply
Post Reply