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 :

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

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

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);
}
};
#endifCode: 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;
}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;
}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.