Cubemapping

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!
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

Well don't worry too much, turns out that wasn't causing my problem and the code required for me to do the swapping is trivial (I don't know about the actual performance but surely it is fractional compared to the actual rendering to texture), was just curious really.

It seems my problem is caused by my attempt to implement an actual cube material, I think this comes from calling settexture on the cubetexture causing the following warning:

Direct3D9: (WARN) :Can not render to a render target that is also used as a texture. A render target was detected as bound, but couldn't detect if texture was actually used in rendering.

the program runs fine when I am just rendering to the cube texture (no idea if it renders correctly because I haven't applied it correctly to anything yet!) but when I try to apply my material I get this warning and ALL textures are distorted!? phunk I was wondering if you had run into this problem?

I'm going to have a closer look this evening..
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Well, done some testing, and got the cube map example working pretty well, going to try some more complex scenes, once I get CUBE textures working in OpenGL( they're broke right now ). Here's some SS's using DX9 -

Image

Image
Image
Phunk
Posts: 78
Joined: Sun Dec 14, 2003 8:18 pm
Location: The Netherlands

Post by Phunk »

Im sorry, but I think I cannot be of any help annymore, because I never got as far as you and Spintz are now. If I remember correctly, I got to the point where I could see the cube texture on the mesh, but because I was still stuggeling to get the correct transformation matrix, I never got any further.

Btw, Nice work Spintz! I am wondering though, will there ever be another release of irrspintz, or are you focusing more on enhancing irrlicht itself?

Either way, good luck to you both!
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

There will be more releases of IrrSpintz, I'm not really focusing on Irrlicht enhancements, unless some cool stuff comes out that I'd like to merge into IrrSpintz, and I always hope my changes for IrrSpintz will make it back into Irrlicht. I only enhance DX9 and OpenGL in IrrSpintz tho, no software or dx8 updates.

I have IrrSpintz-0.15 working great right now. Just been really busy.

BTW, I'm using shaders for doing the reflections onto the sphere from the cube. That's the other thing, I'm focusing on shader performance rather than increasing the FVF with IrrSpintz. The shader is REALLY simple for this. Here it is for HLSL :

Code: Select all

//-----------------------------------------------------------------------------
// Global variables
//-----------------------------------------------------------------------------
float4x4 wvp;
float3   cameraPos;
float    Reflectivity;

// Vertex Shader
void VS( 
	in float4 iPos	: POSITION,
	in float3 iNorm	: NORMAL,
	in float3 iTex  : TEXCOORD0,
	out float4 oPos	: POSITION,
	out float3 oTex	: TEXCOORD0 )
{
	// transform vertex position by combined view projection matrix
    oPos = mul( iPos, wvp );
	
    // create ray from camera position to the vertex, in world space
    float3 V = iPos - cameraPos;
	
    // compute the reflection vector, and assign it to texcoord 0
    oTex = reflect( normalize(V), iNorm );

	// just use the normal for the reflection vector
    //oTex = iNorm;
}

sampler cubeTex: register(s0);
	
float4 PS( float3 iTex : TEXCOORD0 ) : COLOR
{
    return Reflectivity * texCUBE( cubeTex, iTex );
}
And for GLSL, here's the vert program -

Code: Select all

uniform vec3 cameraPos;

void main(void)
{
	gl_Position = ftransform();
	vec3 V = vec3(gl_Vertex) - cameraPos
	gl_TexCoord[0] = reflect( normalize(V), gl_Normal );
}
and the fragment -

Code: Select all

uniform samplerCube cubeTex;

varying vec3 cubeTC;

void main( void )
{
	gl_FragColor = textureCube( cubeTex, cubeTC );
}
Image
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Almost there in OpenGL, it's funny. I have the render targets working and the shaders work, to do the proper reflection -

Image

But those god damned renderstates in OpenGL are a pain in the ass, and so now the CUBE texture stuff renders fine, but everything else doesn't......I hate OpenGL's states.


Here's what my new COpenGLDriver::setTexture function looks like, any OpenGL guru's out there have a clue???

Code: Select all

void COpenGLDriver::setTexture(s32 stage, video::ITexture* texture)
{
	if (stage > 3)
		return;

	if (MultiTextureExtension)
		extGlActiveTextureARB( GL_TEXTURE0_ARB + stage );
	else if (stage != 0)
		return;
	
	if (texture && texture->getDriverType() != EDT_OPENGL)
	{
		glDisable( GL_TEXTURE_2D );
		glDisable( GL_TEXTURE_3D );
		glDisable( GL_TEXTURE_CUBE_MAP_ARB );
		os::Printer::log("Fatal Error: Tried to set a texture not owned by this driver.", ELL_ERROR);
		return;
	}

	if (texture == 0)
	{
		//printf( "Disable ALL TEXTURES for Stage %d\n", stage );
		glDisable( GL_TEXTURE_2D );
		glDisable( GL_TEXTURE_3D );
		glDisable( GL_TEXTURE_CUBE_MAP_ARB );
	}
	else
	{
		switch( texture->getTextureType() )
		{
			case ETT_2D:
				//printf( "Enabled GL_TEXTURE_2D for Stage %d\n", stage );
				glEnable( GL_TEXTURE_2D );
				glDisable( GL_TEXTURE_3D );
				glDisable( GL_TEXTURE_CUBE_MAP_ARB );
				glBindTexture( GL_TEXTURE_2D, ((COpenGLTexture*)texture)->getOpenGLTextureName());
				break;
			case ETT_3D:
				//printf( "Enabled GL_TEXTURE_3D for Stage %d\n", stage );
				glDisable( GL_TEXTURE_2D );
				glEnable( GL_TEXTURE_3D );
				glDisable( GL_TEXTURE_CUBE_MAP_ARB );
				glBindTexture( GL_TEXTURE_3D, ((COpenGLTexture3D*)texture)->getOpenGLTextureName());
				break;
			case ETT_CUBE:
				//printf( "Enabled GL_TEXTURE_CUBE_MAP_ARB for Stage %d\n", stage );
				glDisable( GL_TEXTURE_2D );
				glDisable( GL_TEXTURE_3D );
				glEnable( GL_TEXTURE_CUBE_MAP_ARB );
				glBindTexture( GL_TEXTURE_CUBE_MAP_ARB, ((COpenGLTextureCUBE*)texture)->getOpenGLTextureName() );
				break;
		}
	}
}
Image
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

@phunk, well I think I have actually only got as far as you at the moment, I have the cubemap generated but not mapping correctly to the object, though, like Spintz, I am intending to do this in a shader, I was only creating the material to test that the cubemap was actually generated (I hope to finish it some time, I just have slightly more pressing stuff to do for the next few weeks).

However I think the reason you may not have been able to is that the FVF required doesn't actually exist in Irrlicht (and you didn't metion having added one) - something I haven't done yet either!

As far as I can make out Irrlicht only has 3 vertex formats, none of which contain the neccesary 3D Tex-coords. bleow is the FVF they use in the docs.

DWORD dwFVF = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_TEX1 | D3DFVF_TEXCOORDSIZE3(0);

@Spintz, nice job on the DX. Can't help you on the OGL I'm afraid, my DX skills aren't exactly the greatest let alon my OGL - I hate it.

PS The warning above was caused by rendering the object that i wanted to apply the cubemap to when I was actually rendering the cubemap itself - oops not entirely sure this is garaunteed to cause a problem by itself, my problem was actaully that I had for some reason set the default parameters for clearing the back and z buffer to false when setting a cube face as the render target :? - did not look good
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

hmmm I'm still having problems, not sure if anyone can help but I have just reached a complete dead end, it seems (to me) that the cubemap isn't being rendered properly, I assume it is the camera/matrices that is the problem but I can't figure out whta I need to do..?

Here is a screen, as you can see the 'reflection' is HUGE and it seems to be offset

http://img90.imageshack.us/img90/787/cubeza1.png

Here is my code that renders to the 6 faces of the cubemap

Code: Select all

		if((framecount%5)==0)
		{
			framecount=0;
			plane->setVisible(false);
			for( u32 i=0; i<6; i++ )
			{
				// Standard view that will be overridden below.
				core::vector3df vEnvEyePt = plane->getAbsolutePosition();
				fixedCam->setPosition(vEnvEyePt);
				core::vector3df vLookatPt, vUpVec;
				switch( i )
				{
				case 0:
					vLookatPt = vEnvEyePt + core::vector3df( 1.0f, 0.0f, 0.0f );
					vUpVec    = core::vector3df( 0.0f, 1.0f, 0.0f );
					fixedCam->setTarget(vLookatPt);
					fixedCam->setUpVector(vUpVec);
					break;
				case 1:
					vLookatPt = vEnvEyePt + core::vector3df(-1.0f, 0.0f, 0.0f );
					vUpVec    = core::vector3df( 0.0f, 1.0f, 0.0f );
					fixedCam->setTarget(vLookatPt);
					fixedCam->setUpVector(vUpVec);
					break;
				case 2:
					vLookatPt = vEnvEyePt + core::vector3df( 0.0f, 1.0f, 0.0f );
					vUpVec    = core::vector3df( 0.0f, 0.0f,-1.0f );
					fixedCam->setTarget(vLookatPt);
					fixedCam->setUpVector(vUpVec);
					break;
				case 3:
					vLookatPt = vEnvEyePt + core::vector3df( 0.0f,-1.0f, 0.0f );
					vUpVec    = core::vector3df( 0.0f, 0.0f, 1.0f );
					fixedCam->setTarget(vLookatPt);
					fixedCam->setUpVector(vUpVec);
					break;
				case 4:
					vLookatPt = vEnvEyePt + core::vector3df( 0.0f, 0.0f, 1.0f );
					vUpVec    = core::vector3df( 0.0f, 1.0f, 0.0f );
					fixedCam->setTarget(vLookatPt);
					fixedCam->setUpVector(vUpVec);
					break;
				case 5:
					vLookatPt = vEnvEyePt + core::vector3df( 0.0f, 0.0f,-1.0f );
					vUpVec    = core::vector3df( 0.0f, 1.0f, 0.0f );
					fixedCam->setTarget(vLookatPt);
					fixedCam->setUpVector(vUpVec);
					break;
				}
				core::matrix4 proj;
				proj.buildProjectionMatrixPerspectiveFovLH(core::PI/2, 1.0, 1.0, 2000.0);
				fixedCam->setProjectionMatrix(proj);
				smgr->setActiveCamera(fixedCam);

				driver->setRenderTargetCubeFace(texCubeMap, i, true, true, video::SColor(255,255,255,255));
				//Draw scene manager
				smgr->drawAll();
				driver->setRenderTargetCubeFace(texCubeMap, i,  true, true, video::SColor(255,255,255,255));
				//Draw scene manager
				smgr->drawAll();
				driver->setRenderTargetCubeFace(texCubeMap, i,  true, true, video::SColor(255,255,255,255));
				//Draw scene manager
				smgr->drawAll();
				driver->setRenderTargetCubeFace(texCubeMap, i,  true, true, video::SColor(255,255,255,255));
				//Draw scene manager
				smgr->drawAll();
				driver->setRenderTargetCubeFace(texCubeMap, i,  true, true, video::SColor(255,255,255,255));
				//Draw scene manager
				smgr->drawAll();
				driver->setRenderTargetCubeFace(texCubeMap, i,  true, true, video::SColor(255,255,255,255));
				//Draw scene manager
				smgr->drawAll();
				driver->setRenderTarget(0, true, true, video::SColor(255,113,113,133));

			}
			smgr->setActiveCamera(fpsCam);
		}
		plane->setVisible(true);
Tho I don't actaully believe there are any problems with the shader that applies the cubemap (it works fine in rendermonkey) here is all the relevant shader stuff

Code: Select all

#line 2 "cubemap.hlsl"
float4x4 view_proj_matrix;
float4 view_position;
struct VS_OUTPUT 
{
   float4 Pos:       POSITION;
   float3 Reflect:   TEXCOORD0;
};

VS_OUTPUT vs_main(float4 inPos: POSITION, float3 inNormal: NORMAL)
{
   VS_OUTPUT Out;

   // Compute the projected position and send out the texture coordinates
   Out.Pos = mul(inPos,view_proj_matrix);
   //Out.TexCoord = inTxr;
   
	float4 look = inPos-view_position;
	
   // Compute the reflection vector
   Out.Reflect = reflect(normalize(look),inNormal);

   return Out;
}

sampler EnvMap;
float4 ps_main(float3 inReflect: TEXCOORD0) : COLOR 
{
   // Output texture color with reflection map
   return texCUBE(EnvMap,inReflect);
}

Code: Select all

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

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

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

		core::vector3df pos = device->getSceneManager()->
			getActiveCamera()->getPosition();
		video::SColorf campos(pos.X, pos.Y, pos.Z, 1.0f);

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

Code: Select all

MyShaderCallBack* mc = new MyShaderCallBack();

			newMaterialType1 = gpu->addHighLevelShaderMaterialFromFiles(
				"../../media/cubemap.hlsl",	"vs_main", video::EVST_VS_2_0,
				"../../media/cubemap.hlsl", "ps_main", video::EPST_PS_2_0,
				mc, video::EMT_SOLID);
I'd really appreciate any suggestions because this has started driving me mad! Thanks
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

I think you're problem is that you are rendering into every face of the render target every frame. So on you're last face( i == 5 ) you are rendering the negative Z view into all faces of the cube map.

Try this -

Code: Select all

      // Only need to do this once
      core::matrix4 proj; 
      proj.buildProjectionMatrixPerspectiveFovLH(core::PI/2, 1.0, 1.0, 2000.0); 
      fixedCam->setProjectionMatrix(proj); 

      if((framecount%5)==0) 
      { 
         framecount=0; 
         plane->setVisible(false); 
		 smgr->setActiveCamera(fixedCam); 
         fixedCam->setPosition( plane->getAbsolutePosition() ); 
         core::vector3df vLookatPt, vUpVec; 
         for( u32 i=0; i<6; i++ ) 
         { 
            // Standard view that will be overridden below. 
            switch( i ) 
            { 
            case 0: 
               // positive X of cube
               vLookatPt = vEnvEyePt + core::vector3df( 1.0f, 0.0f, 0.0f ); 
               vUpVec    = core::vector3df( 0.0f, 1.0f, 0.0f ); 
               fixedCam->setTarget(vLookatPt); 
               fixedCam->setUpVector(vUpVec); 
               driver->setRenderTargetCubeFace(texCubeMap, i, true, true, video::SColor(255,255,255,255)); 
			   smgr->drawAll();
               break; 
            case 1: 
               // negative X of cube
               vLookatPt = vEnvEyePt + core::vector3df(-1.0f, 0.0f, 0.0f ); 
               vUpVec    = core::vector3df( 0.0f, 1.0f, 0.0f ); 
               fixedCam->setTarget(vLookatPt); 
               fixedCam->setUpVector(vUpVec); 
               driver->setRenderTargetCubeFace(texCubeMap, i, true, true, video::SColor(255,255,255,255)); 
			   smgr->drawAll();
               break; 
            case 2: 
               // positive Y of cube
               vLookatPt = vEnvEyePt + core::vector3df( 0.0f, 1.0f, 0.0f ); 
               vUpVec    = core::vector3df( 0.0f, 0.0f,-1.0f ); 
               fixedCam->setTarget(vLookatPt); 
               fixedCam->setUpVector(vUpVec); 
               driver->setRenderTargetCubeFace(texCubeMap, i, true, true, video::SColor(255,255,255,255)); 
			   smgr->drawAll();
               break; 
            case 3: 
               // negative Y of cube
               vLookatPt = vEnvEyePt + core::vector3df( 0.0f,-1.0f, 0.0f ); 
               vUpVec    = core::vector3df( 0.0f, 0.0f, 1.0f ); 
               fixedCam->setTarget(vLookatPt); 
               fixedCam->setUpVector(vUpVec); 
               driver->setRenderTargetCubeFace(texCubeMap, i, true, true, video::SColor(255,255,255,255)); 
			   smgr->drawAll();
               break; 
            case 4: 
               // positive Z of cube
               vLookatPt = vEnvEyePt + core::vector3df( 0.0f, 0.0f, 1.0f ); 
               vUpVec    = core::vector3df( 0.0f, 1.0f, 0.0f ); 
               fixedCam->setTarget(vLookatPt); 
               fixedCam->setUpVector(vUpVec); 
               driver->setRenderTargetCubeFace(texCubeMap, i, true, true, video::SColor(255,255,255,255)); 
			   smgr->drawAll();
               break; 
            case 5: 
               // negative Z of cube
               vLookatPt = vEnvEyePt + core::vector3df( 0.0f, 0.0f,-1.0f ); 
               vUpVec    = core::vector3df( 0.0f, 1.0f, 0.0f ); 
               fixedCam->setTarget(vLookatPt); 
               fixedCam->setUpVector(vUpVec); 
               driver->setRenderTargetCubeFace(texCubeMap, i, true, true, video::SColor(255,255,255,255)); 
			   smgr->drawAll();
               break; 
            } 
         } 
         driver->setRenderTarget(0);
         smgr->setActiveCamera(fpsCam); 
      } 
      plane->setVisible(true);
Image
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

Thanks for the reply Spintz but that doesn't seem to be the problem. Still get the same result. thanks for taking the time anyway.
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Try this, in your shader, change -

Code: Select all

...
sampler EnvMap; 
...
to

Code: Select all

...
sampler EnvMap: register(s0); 
...
There's nothing else wrong in your code that I can see. Any other problems may lie in how the CUBE texture is created in the D3D9Driver.
Image
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

Yeah I was beginning to worry that mat be where the problem lies, it almost seems as if the scene is being rendered to a huge surface and the cube is just ten using its 512x512 peice of it?
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

funcdoobiest wrote:Yeah I was beginning to worry that mat be where the problem lies, it almost seems as if the scene is being rendered to a huge surface and the cube is just ten using its 512x512 peice of it?
Is this in reply to the fix I posted on setting up the render target camera, or to the shader?

The problem in your shader, is that HLSL needs to specify which sampler is using the texture from a certain texture stage. Adding the "register(s0)" is for PS 2.0 or greater( in the PS 1.x, you must use "regsiter(t0)" ).

I can't see anything else wrong though. I'll be releasing IrrSpintz-0.15 soon, and then you can compare the sources.
Image
funcdoobiest
Posts: 48
Joined: Thu Jun 15, 2006 6:35 pm

Post by funcdoobiest »

Sorry should have been clearer, that seemed to make no difference, I think that was just me being lazy and assuming the shader picks up the register automatically but changing it had no effect. I was just sayin that that the size thing was how the problem looked to me, anyway it must be someting to do with my engine side code, I'll have a closer look at it. Cheers Spintz
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

hey, this thread is cool.

thanks for the code, i'll try this one right away.

i have only read some of the messages, though i'm still wondering if the posted code will run on irrlicht 1.4
Image
dlangdev
Posts: 1324
Joined: Tue Aug 07, 2007 7:28 pm
Location: Beaverton OR
Contact:

Post by dlangdev »

Any new cubemap developments?

I was able to do testing HDR env map and HDR cubemap on a different engine, though I'm still wondering what is the status of this one lately.

Or maybe this feature will never see the light of day?

By the way, the image below are the images I used to test cubemapping but that was on a different engine.

Image
Image
Post Reply