[OPENGL]Can not use MultiTexture?

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
shine5128
Posts: 5
Joined: Sun May 02, 2010 12:14 pm

[OPENGL]Can not use MultiTexture?

Post by shine5128 »

Hi, every one.

I testing OPENGL MultiTexture has trouble. :(

see:
http://cid-5d5624a46b4eca1c.skydrive.li ... e/test.jpg


the code:

Code: Select all

/** Example 010 Shaders

This tutorial shows how to use shaders for D3D8, D3D9, and OpenGL with the
engine and how to create new material types with them. It also shows how to
disable the generation of mipmaps at texture loading, and how to use text scene
nodes.

This tutorial does not explain how shaders work. I would recommend to read the
D3D or OpenGL documentation, to search a tutorial, or to read a book about
this.

At first, we need to include all headers and do the stuff we always do, like in
nearly all other tutorials:
*/
#include <irrlicht.h>
#include <iostream>

using namespace irr;

#ifdef _MSC_VER
#pragma comment(lib, "Irrlicht.lib")
#endif

IrrlichtDevice* device = 0;

int main()
{
	// create device
	device = createDevice(video::EDT_OPENGL, core::dimension2d<u32>(640, 480));

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

	video::IVideoDriver* driver = device->getVideoDriver();
	scene::ISceneManager* smgr = device->getSceneManager();
	gui::IGUIEnvironment* gui = device->getGUIEnvironment();

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

	if (gpu)
	{
		newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
			"../../media/opengl.vert", "main", video::EVST_VS_1_1,
			"../../media/opengl.frag", "main", video::EPST_PS_1_1,
			0, video::EMT_SOLID);

	}

	// create test scene node 1, with the new created material type 1
	scene::ISceneNode* node = smgr->addCubeSceneNode(50);
	node->setPosition(core::vector3df(0,0,0));
	node->setMaterialTexture(0, driver->getTexture("../../media/wall.bmp"));
	node->setMaterialTexture(1, driver->getTexture("../../media/lightFalloff.png"));
	node->setMaterialFlag(video::EMF_LIGHTING, false);
	node->setMaterialType((video::E_MATERIAL_TYPE)newMaterialType1);

	smgr->addTextSceneNode(gui->getBuiltInFont(),
			L"PS & VS & EMT_SOLID",
			video::SColor(255,255,255,255),	node);

	scene::ISceneNodeAnimator* anim = smgr->createRotationAnimator(
			core::vector3df(0,0.3f,0));
	node->addAnimator(anim);
	anim->drop();

	// add a nice skybox
	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, false);

	smgr->addSkyBoxSceneNode(
		driver->getTexture("../../media/irrlicht2_up.jpg"),
		driver->getTexture("../../media/irrlicht2_dn.jpg"),
		driver->getTexture("../../media/irrlicht2_lf.jpg"),
		driver->getTexture("../../media/irrlicht2_rt.jpg"),
		driver->getTexture("../../media/irrlicht2_ft.jpg"),
		driver->getTexture("../../media/irrlicht2_bk.jpg"));

	driver->setTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS, true);

	// add a camera and disable the mouse cursor
	scene::ICameraSceneNode* cam = smgr->addCameraSceneNode();
	cam->setPosition(core::vector3df(-100,50,100));
	cam->setTarget(core::vector3df(0,0,0));


	int lastFPS = -1;
	while(device->run())
		if (device->isWindowActive())
	{
		driver->beginScene(true, true, video::SColor(255,0,0,0));
		smgr->drawAll();
		driver->endScene();

		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
			core::stringw str = L"Irrlicht Engine - Vertex and pixel shader example [";
			str += driver->getName();
			str += "] FPS:";
			str += fps;

			device->setWindowCaption(str.c_str());
			lastFPS = fps;
		}
	}

	device->drop();

	return 0;
}
"../../media/opengl.vert"

Code: Select all

varying vec2 _texCoord;

void main(void)
{
	gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
	_texCoord = gl_MultiTexCoord0;
}
"../../media/opengl.frag"

Code: Select all

uniform sampler2D myTexture;
uniform sampler2D myTestTexture;

varying vec2 _texCoord;

void main (void)
{
    vec4 col = texture2D(myTexture, _texCoord);
    col *= texture2D(myTestTexture, _texCoord);

    gl_FragColor = col;
}
wall.bmp and lightFalloff.png size: 256x256.

but myTexture = myTestTexture...

help!!

sorry for my very very very bad english. :(
Viz_Fuerte
Posts: 91
Joined: Sun Oct 19, 2008 5:29 pm
Location: Valencia (Spain)
Contact:

Post by Viz_Fuerte »

The first thing to do multitexture with shaders, is that you create something like this:

Code: Select all

class MyShaderCallBack : public video::IShaderConstantSetCallBack
{
public:

	virtual void OnSetConstants(video::IMaterialRendererServices* services,s32 userData)
	{
		int index[] = {0,1};
		services->setPixelShaderConstant("myTexture",reinterpret_cast<f32*>(&index[0]),1);
		services->setPixelShaderConstant("myTestTexture",reinterpret_cast<f32*>(&index[1]),1);

	}

};

......

MyShaderCallBack* mc = new MyShaderCallBack();

......

      newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
         "../../media/opengl.vert", "main", video::EVST_VS_1_1,
         "../../media/opengl.frag", "main", video::EPST_PS_1_1,
         mc, video::EMT_SOLID); 

......
You must assign the route of each texture.
shine5128
Posts: 5
Joined: Sun May 02, 2010 12:14 pm

Post by shine5128 »

Wow! Thanks Viz_Fuerte! :wink:
Vamp
Posts: 5
Joined: Mon Nov 23, 2009 9:53 am

Post by Vamp »

Hi,
I tried to use your example. I have exactly the same code, but when I run the program the error

Code: Select all

`gl_FragColor` : undeclared identifier
`assign` :  cannot convert from `4-component vector of float`to `float`
occured.
Can anybody help me?

The next question is - can I use shaders like this for rendering the whole scene? I think the only way how to use shaders for the whole scene from tho cameras positions is to render the scene to texture (twice) and these two textures to use in shader... Am I right?
arras
Posts: 1622
Joined: Mon Apr 05, 2004 8:35 am
Location: Slovakia
Contact:

Post by arras »

This works for me, try it:

Code: Select all

class ShaderCallBack : public video::IShaderConstantSetCallBack
{
public:

  virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
  {
      int texture0 = 0;
      services->setPixelShaderConstant("texture0", (float*)(&texture0), 1);

      int texture1 = 1;
      services->setPixelShaderConstant("texture1", (float*)(&texture1), 1);
  }
};
Then in fragment shader:

Code: Select all

uniform sampler2D texture0, texture1;
...
EDIT: error message suggest that you do something wrong while assigning gl_FragColor some wrong value (you should assign vector but assign float). So check that line in your fragment shader.

You set gl_FragColor like this for example:

Code: Select all

gl_FragColor = texture2D(texture0, gl_TexCoord[0].st) *
      texture2D(texture1, gl_TexCoord[0].st);
Vamp
Posts: 5
Joined: Mon Nov 23, 2009 9:53 am

Post by Vamp »

Thanks,
I combinated advices that were written here with irrlicht official tutorials and everything works well.
Now I will try to get all my work together and finaly create classes and shaders for stereoscopics vision in Irrlicht.
shine5128
Posts: 5
Joined: Sun May 02, 2010 12:14 pm

Post by shine5128 »

Well, again sorry my English is very bad. Makes it difficult to understand your reply.

PS: thanks Google Translate feature. :wink:

If you are using DIRECTX, please continue to read on.

About your question, this is my opinion. Above shader language is GLSL, So only run in OPENGL.

So you can conversion the shader: GLSL to HLSL.

This my conversion version shader:

Code: Select all

float4x4 mWorldViewProj;  // World * View * Projection transformation

struct VS_OUTPUT
{
	float4 Position   : POSITION;   // vertex position 
	float2 TexCoord   : TEXCOORD0;  // tex coords
};


VS_OUTPUT vertexMain( in float4 vPosition : POSITION,
                      float2 texCoord     : TEXCOORD0 )
{
	VS_OUTPUT Output;

	// transform position to clip space 
	Output.Position = mul(vPosition, mWorldViewProj);

	Output.TexCoord = texCoord;

	return Output;
}


sampler2D tex0, tex1;
	
float4 pixelMain( float2 TexCoord : TEXCOORD0,
                     float4 Position : POSITION ) : COLOR0
{ 

	return tex2D( tex0, TexCoord ) * tex2D( tex1, TexCoord );
}

And your event class:

Code: Select all

class ShaderCallBack : public video::IShaderConstantSetCallBack
{
public:

  virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
  {
	core::matrix4 worldViewProj;
	worldViewProj = driver->getTransform(video::ETS_PROJECTION);
	worldViewProj *= driver->getTransform(video::ETS_VIEW);
	worldViewProj *= driver->getTransform(video::ETS_WORLD);

	services->setVertexShaderConstant("mWorldViewProj", worldViewProj.pointer(), 16);

  }
};
Post Reply