ALMOST GOOD RTT REFRACTION SHADER DEMO (with source)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
Post Reply
belfegor
Posts: 383
Joined: Mon Sep 18, 2006 7:22 pm
Location: Serbia

ALMOST GOOD RTT REFRACTION SHADER DEMO (with source)

Post by belfegor »

The ATI TreasureChest Demo has refraction shader sample
witch i didnt get it to work with irrlicht because its
writen in asembly.So i have spend lot of time with various shader tutorials,
post processing sample codes and write a solid looking refraction HLSL shader.

Some of the code is based from DeusXL water shader(camera setup, targeting).
The stained-glass window and bumpmap textureare from the
ATI TreasureChest demo(stainedGlass_RGB.bmp and stainedGlass_bump.bmp).
I save them as .JPEG-s to upload them faster (since here is slow upload on
this PC that i am using for internet), and they are low quality.
Rest of resources you can find in irrlicht SDK media folder.

TERRIBLE BUG :
when my camera (fps camera position) is above centre of the
window node (HillPlaneMesh) and i tilt camera up a bit window node disapeirs
(when tilted down it dont disapeirs),
and when camera is below centre and i tilt down window disapeirs too
(when tilted up it dont disapeirs).
I have also tried with "plane" model (.b3d) its the same.
Can someone point where this problem is (probably have to do something
with camera).PLEASE HELP.

It is strange that shader somehow rotates model +90 by X axis
and i dont know why???


Here is the screenshot :

Image

Here is stainedGlass_RGB.jpg (i added 40 % brightness to this image
because i have old monitor witch display is very dark) :

Image

and stainedGlass_bump.jpg (to get idea how they look like) :

Image

CRefraction.h

Code: Select all

#ifndef _CREFRACTION_H 
#define _CREFRACTION_H 

#include <irrlicht.h> 
using namespace irr;

const irr::c8* REFRACTION_HLSL = "refract.hlsl";

class CRefraction : public video::IShaderConstantSetCallBack 
{ 
public:
	IrrlichtDevice*            m_pDevice; 
    scene::ISceneNode*         m_pWindowNode; 
    scene::ICameraSceneNode*   m_pRtCamera; 
    video::ITexture*           m_pRtTexture;
	video::ITexture*           m_pBumpTexture;
	video::ITexture*           m_pDiffuseTexture;
    float                      m_refractionDisplacement;
	float                      m_colorStrength;
public:  
	CRefraction(IrrlichtDevice *device, float refractionDisplacement = 0.008f, float colorStrength = 2.5f)
	{
		m_pDevice                = device; 
		m_refractionDisplacement = refractionDisplacement;
		m_colorStrength          = colorStrength;

		m_pBumpTexture    = m_pDevice->getVideoDriver()->getTexture("stainedGlass_bump.bmp");
		m_pDiffuseTexture = m_pDevice->getVideoDriver()->getTexture("stainedGlass_RGB.bmp");

		scene::IAnimatedMesh* windowMesh = 
		m_pDevice->getSceneManager()->addHillPlaneMesh(
			"refractedWindow", core::dimension2d<f32>(100, 200), core::dimension2d<s32>(1, 1));  

		m_pWindowNode = m_pDevice->getSceneManager()->addMeshSceneNode(windowMesh->getMesh(0)); 

		s32 refractionMaterial = 0;
		video::IGPUProgrammingServices *gpu = m_pDevice->getVideoDriver()->getGPUProgrammingServices(); 
		refractionMaterial = gpu->addHighLevelShaderMaterialFromFiles( 
			REFRACTION_HLSL, "vertexMain", video::EVST_VS_1_1, 
			REFRACTION_HLSL, "pixelMain", video::EPST_PS_2_0, 
			this, video::EMT_TRANSPARENT_ALPHA_CHANNEL); 
		m_pWindowNode->setMaterialType((video::E_MATERIAL_TYPE)refractionMaterial); 
        m_pWindowNode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false); 
        m_pWindowNode->setMaterialFlag(video::EMF_LIGHTING, false); 
        m_pWindowNode->setMaterialFlag(video::EMF_FOG_ENABLE, false); 
		m_pRtTexture = m_pDevice->getVideoDriver()->createRenderTargetTexture(
			core::dimension2d<s32>(512, 512)); 
		m_pWindowNode->setMaterialTexture(0, m_pRtTexture);
		m_pWindowNode->setMaterialTexture(1, m_pBumpTexture);
		m_pWindowNode->setMaterialTexture(2, m_pDiffuseTexture);

		scene::ICameraSceneNode* camera = m_pDevice->getSceneManager()->getActiveCamera(); 
		m_pRtCamera = m_pDevice->getSceneManager()->addCameraSceneNode(); 
		m_pDevice->getSceneManager()->setActiveCamera(camera);
	}

	~CRefraction()
	{
		m_pRtTexture->drop();
	}

	void updateRenderTarget(scene::ISceneManager* smgr, video::IVideoDriver* driver)
	{
		scene::ICameraSceneNode *camera = smgr->getActiveCamera(); 
		m_pRtCamera->setFarValue(camera->getFarValue()); 
		core::vector3df position = m_pWindowNode->getPosition(); 
        core::vector3df campos   = camera->getPosition(); 
		
		m_pRtCamera->setPosition(camera->getPosition());             
		core::vector3df target = camera->getTarget() - camera->getPosition(); 
        target.normalize(); 
        target *= 200000; 
        m_pRtCamera->setTarget(m_pRtCamera->getPosition() + target); 
        m_pRtCamera->setUpVector(camera->getUpVector()); 
 
		driver->setRenderTarget(m_pRtTexture, true, true, video::SColor(0,100,100,100)); 
		smgr->setActiveCamera(m_pRtCamera); 
		m_pWindowNode->setVisible(false); 
		smgr->drawAll();                  
		driver->setRenderTarget(0); 
		m_pWindowNode->setVisible(true); 
		smgr->setActiveCamera(camera);
	}

	virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
	{ 
		video::IVideoDriver* driver = services->getVideoDriver(); 
		
		core::matrix4 WVPMatrix;
	    WVPMatrix  = driver->getTransform(video::ETS_PROJECTION);
	    WVPMatrix *= driver->getTransform(video::ETS_VIEW);
		WVPMatrix *= driver->getTransform(video::ETS_WORLD);
		services->setVertexShaderConstant("WVPMatrix", &WVPMatrix.M[0], 16);

		services->setPixelShaderConstant("refractionDisplacement", &m_refractionDisplacement, 1);
		services->setPixelShaderConstant("colorStrength", &m_colorStrength, 1);
	} 
}; 
#endif
main.h

Code: Select all

#include <windows.h>
#include <irrlicht.h> 
using namespace irr; 
#pragma comment(lib, "Irrlicht.lib") 

#include "CRefraction.h"

const s32 winWidth  = 800;
const s32 winHeight = 600;
IrrlichtDevice* device = 0;

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 true;
		}
		return false;
	}
};


int main() 
{  
	MyEventReceiver receiver;
	SIrrlichtCreationParameters param;
	param.AntiAlias               = false;
	param.Bits                    = 32;
	param.DriverType              = video::EDT_DIRECT3D9;
	param.EventReceiver           = &receiver;
	param.Fullscreen              = false;
	param.HighPrecisionFPU        = true;
	param.Stencilbuffer           = false;
	param.Vsync                   = false;
	param.WindowSize.Width        = winWidth;
	param.WindowSize.Height       = winHeight;
	device                        = createDeviceEx(param);   

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

	if (!driver->queryFeature(video::EVDF_RENDER_TO_TARGET) || 
		!driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0))
	{
		MessageBox(NULL,
               L"Your hardware can't run this demo",
               L"ERROR",
               MB_ICONEXCLAMATION | MB_OK);
		device->closeDevice();
	}

	driver->setTextureCreationFlag(video::ETCF_ALWAYS_32_BIT, true);
	driver->setTextureCreationFlag(video::ETCF_OPTIMIZED_FOR_QUALITY, true);

	device->getCursorControl()->setVisible(false);

	scene::ICameraSceneNode* camera = 
		smgr->addCameraSceneNodeFPS(0,100.0f,300.0f); 
    camera->setPosition(core::vector3df(-100.0f, 180.0f, -200.0f));

	scene::IAnimatedMesh* roomMesh  = smgr->getMesh("room.3ds");
	smgr->getMeshManipulator()->makePlanarTextureMapping( 
			roomMesh->getMesh(0), 0.003f);
	scene::IAnimatedMeshSceneNode* aRoomMesh = smgr->addAnimatedMeshSceneNode(roomMesh);
	aRoomMesh->setMaterialTexture(0, driver->getTexture("rockwall.bmp"));
	aRoomMesh->setMaterialFlag(video::EMF_LIGHTING, false);

    CRefraction* refract = new CRefraction(device, 0.02f, 2.0f); 
    refract->m_pWindowNode->setPosition(core::vector3df(-100.0f, 180.0f, -120.0f));

	int lastFPS = -1;

	while(device->run()) 
	{ 
		driver->beginScene(true, true, 0); 
        refract->updateRenderTarget(smgr, driver);
        smgr->drawAll();  
        driver->endScene();
		int fps = driver->getFPS();

		if (lastFPS != fps)
		{
		  core::stringw str = L"Belfegor's refraction demo - Irrlicht Engine [";
		  str += driver->getName();
		  str += "] FPS:";
		  str += fps;

		  device->setWindowCaption(str.c_str());
		  lastFPS = fps;
		}
    }
	if(refract)
		refract->drop();
	device->drop();     
	return 0; 
}
refraction.hlsl

Code: Select all

float4x4 WVPMatrix;
float    refractionDisplacement;
float    colorStrength;

struct VS_OUTPUT 
{
   float4 Pos        : POSITION;
   float2 texCoord   : TEXCOORD0;
   float3 eyeLinear  : TEXCOORD1;
};

VS_OUTPUT vertexMain(float4 Pos      : POSITION,
                     float2 texCoord : TEXCOORD0)
{
   VS_OUTPUT Out;

   Out.Pos         = mul(Pos, WVPMatrix);

   float4 sPos     = mul(float4(Pos.xzy, 1), WVPMatrix);
   Out.Pos         = sPos;
   
   Out.eyeLinear.x = 0.5 * (sPos.z + sPos.x);
   Out.eyeLinear.y = 0.5 * (sPos.z - sPos.y);
   Out.eyeLinear.z = sPos.z;
   Out.texCoord    = texCoord;
   
   return Out;
}

sampler renderTexture;
sampler bump;
sampler diffuse;

float4 pixelMain(float3 texCoord: TEXCOORD0,
                 float3 eyeLinear: TEXCOORD1) : COLOR 
{
   float4 normal = 2.0 * tex2D(bump, texCoord) - 1.0;
   float2 coord  = eyeLinear.xy / eyeLinear.z;
   float4 refr   = tex2D(renderTexture, coord + refractionDisplacement * normal.xy);
   float4 diff   = tex2D(diffuse, texCoord) * colorStrength;
   
   return (refr * diff) + refr;
}
Can someone show me (if it is posible) to put bump texture into
diffuse texture alpha channel.Maybie then it would be posible
for demo to work with vs1.1 ps 1.4 like ATI TreasureCHest demo do.
Small FPS demo made using Irrlicht&NewtonDEMO
InfoHERE
Its at very early stage but i think im crazy enough to finish it all alone.
belfegor
Posts: 383
Joined: Mon Sep 18, 2006 7:22 pm
Location: Serbia

Post by belfegor »

Iv puted stainedGlass_bump into stainedGlass_RGB alpha channel
and now pixel shader looks like this:

Code: Select all

sampler renderTexture;
sampler diffuse;

float4 pixelMain(float3 texCoord: TEXCOORD0,
                 float3 eyeLinear: TEXCOORD1) : COLOR
{
   float4 normal = 2.0 * tex2D(diffuse, texCoord).a - 1.0;
   float2 coord  = eyeLinear.xy / eyeLinear.z;
   float4 refr   = tex2D(renderTexture, coord + refractionDisplacement * normal.xy);
   float4 diff   = tex2D(diffuse, texCoord) * colorStrength;
   
   return (refr * diff) + refr;
}
you have to update CRefraction.h too.

Still dont know why it disapeirs. :cry:
Small FPS demo made using Irrlicht&NewtonDEMO
InfoHERE
Its at very early stage but i think im crazy enough to finish it all alone.
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

Maybe irrlicht is creating a bad bounding box for that model (or the BB check is faulty in this special case) why not try the shader with a testscenode(i think its now the cubescenenode)

as for the 90 degrees, your transform part in the vertex shader looks fine. :?
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
omaremad
Competition winner
Posts: 1027
Joined: Fri Jul 15, 2005 11:30 pm
Location: Cairo,Egypt

Post by omaremad »

No it isnt! i didnt read carefully

Out.Pos = mul(Pos, WVPMatrix);

float4 sPos = mul(float4(Pos.xzy, 1), WVPMatrix);
Out.Pos = sPos;
whats the third line doing the first isnt doing? just use the first line and dont used that castsed vertex position

Out.Pos = mul(Pos, WVPMatrix);

float4 sPos = mul(float4(Pos.xzy, 1), WVPMatrix);
"Irrlicht is obese"

If you want modern rendering techniques learn how to make them or go to the engine next door =p
belfegor
Posts: 383
Joined: Mon Sep 18, 2006 7:22 pm
Location: Serbia

Post by belfegor »

Thanks.I will try your changes.
Small FPS demo made using Irrlicht&NewtonDEMO
InfoHERE
Its at very early stage but i think im crazy enough to finish it all alone.
Post Reply