[C++] Reflective Water (conversion from .NET)

Post those lines of code you feel like sharing or find what you require for your project here; or simply use them as tutorials.
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

[C++] Reflective Water (conversion from .NET)

Post by sio2 »

DeusXL made a really nice *OpenGL* demo in .NET showing reflective water. I have converted it to C++ and present the code here.

Topic discussion (and screenshot) here:
http://irrlicht.sourceforge.net/phpBB2/ ... 2&start=64

A C++ class is used for the reflective water technique, so it is easily reusable.

NOTE: You will need the demo from the forum post above for the files used by the demo.

ISSUES: Castle mesh in demo is missing textures (3ds loader?). *** Works fully in OpenGL only ***.

UPDATE: SViewFrustrum is now exposed in SVN irrlicht.h.

Class CReflectedWater.cpp:

Code: Select all

//
// Reflected Water.
// sio2 'at' users.sourceforge.net
// Based on .NET code by DeusXL (Irrlicht forum)
//

#include "CReflectedWater.h"
#include "CReflectedWater_ShaderCode.h"

CReflectedWater::CReflectedWater(const irr::c8 *name, IrrlichtDevice *device, scene::ISceneManager* smgr,
								 s32 id, f32 tileSize, s32 tileCount, core::dimension2di RenderTargetSize)
{
	m_device	= device;
	m_smgr		= smgr;
	m_name		= name;

	// Init constants
	m_AddedColor		= video::SColor(255, 1, 1, 30);
	m_MultiColor		= video::SColor(255, 190, 190, 210);
	m_WaveHeight		= 3.0f;
	m_WaveLength		= 50.0f;
	m_WaveSpeed			= 10.0f;
	m_WaveDisplacement	= 7.0f;
	m_WaveRepetition	= 5.0f;
    m_RefractionFactor	= 0.8f;

	scene::IAnimatedMesh *wmesh =  smgr->addHillPlaneMesh(m_name, core::dimension2df(tileSize, tileSize), core::dimension2di(tileCount, tileCount));
	if (!wmesh) return;
	m_waternode = smgr->addMeshSceneNode(wmesh->getMesh(0));
	if (!m_waternode) return;

	s32 dmat = irr::video::EMT_SOLID;

	video::IVideoDriver* _driver = smgr->getVideoDriver();
	video::E_DRIVER_TYPE edt = _driver->getDriverType();
	video::IGPUProgrammingServices *gpu = _driver->getGPUProgrammingServices();
	if (edt == video::EDT_OPENGL) {
        dmat = gpu->addHighLevelShaderMaterial(
			WATER_VERTEX_GLSL, "main", video::EVST_VS_1_1,
		 WATER_FRAGMENT_GLSL, "main", video::EPST_PS_1_1,
		 this, video::EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
	} else {
        dmat = gpu->addHighLevelShaderMaterial(
         WATER_HLSL, "vertexMain", video::EVST_VS_2_0,
		 WATER_HLSL, "pixelMain", video::EPST_PS_2_0,
		 this, video::EMT_TRANSPARENT_ALPHA_CHANNEL, 2);
	}

	m_waternode->setMaterialType((video::E_MATERIAL_TYPE)dmat);
    m_waternode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
    m_waternode->setMaterialFlag(video::EMF_LIGHTING, false);
    m_waternode->setMaterialFlag(video::EMF_FOG_ENABLE, false);

	m_rt = _driver->createRenderTargetTexture(RenderTargetSize);
    m_waternode->setMaterialTexture(0, m_rt); 

	scene::ICameraSceneNode *camera = smgr->getActiveCamera();
	m_watercam = smgr->addCameraSceneNode();
	smgr->setActiveCamera(camera);
}

// --------------------------------------------------------------------------

CReflectedWater::~CReflectedWater()
{
	m_rt->drop();
}

// --------------------------------------------------------------------------

void CReflectedWater::updateRendertarget(scene::ISceneManager* smgr)
{
	if (!(m_rt && m_waternode && smgr))
		return;

	video::IVideoDriver* driver = smgr->getVideoDriver();
	if (!driver) return;
	
	scene::ICameraSceneNode *camera = smgr->getActiveCamera();
	m_watercam->setFarValue(camera->getFarValue());
	core::vector3df Position = m_waternode->getPosition();
	core::vector3df campos = camera->getPosition();
    if (campos.Y >= Position.Y)
   	{                      	
		m_watercam->setPosition(core::vector3df(campos.X, 2 * Position.Y - campos.Y, campos.Z));
		core::vector3df target = camera->getTarget() - campos;
		target.normalize();
        target.Y *= -1;
        m_watercam->setTarget(m_watercam->getPosition() + target * 20000);
		m_watercam->setUpVector(camera->getUpVector());
   }
   else
   {
       	m_watercam->setPosition(camera->getPosition());
           
		core::vector3df target = camera->getTarget() - camera->getPosition();
		target.normalize();
		target *= 200000;
       	m_watercam->setTarget(m_watercam->getPosition() + target);
       	m_watercam->setUpVector(camera->getUpVector());
	}

	driver->setRenderTarget(m_rt, true, true, video::SColor(0,100,100,100));
	smgr->setActiveCamera(m_watercam);
	m_waternode->setVisible(false);
	smgr->drawAll();                 
	driver->setRenderTarget(0);
	m_waternode->setVisible(true);
	smgr->setActiveCamera(camera);
}

// --------------------------------------------------------------------------

void CReflectedWater::OnSetConstants(video::IMaterialRendererServices* services, s32 userData)
{
	if (!services) return;
	video::IVideoDriver* driver = services->getVideoDriver();
	if (!driver || !m_device) return;

	if (userData == 2 || userData == 3) //All DirectX Shaders
	{
		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.M[0], 16);
	}
/*	if (userData == 1 || userData == 3) //Clamp Shaders
	{
		if (userData == 1) //OpenGL Clamp Shader
		{
			services->setPixelShaderConstant("DiffuseMap", 0f);
			services->setPixelShaderConstant("DetailMap", 1f);
		}
		services->setPixelShaderConstant("WaterPositionY", WaterNode.Position.Y);
		return;
	}*/

	//Water Shaders
	float time = (float)m_device->getTimer()->getRealTime();
	services->setVertexShaderConstant("Time", &time, 1);
	services->setVertexShaderConstant("WaveHeight", &m_WaveHeight, 1);
	services->setVertexShaderConstant("WaveLength", &m_WaveLength, 1);
	services->setVertexShaderConstant("WaveSpeed", &m_WaveSpeed, 1);

	services->setPixelShaderConstant("AddedColor", reinterpret_cast<f32*>(&m_AddedColor), 4);
	services->setPixelShaderConstant("MultiColor", reinterpret_cast<f32*>(&m_MultiColor), 4);
	services->setPixelShaderConstant("WaveDisplacement", &m_WaveDisplacement, 1);
	services->setPixelShaderConstant("WaveRepetition", &m_WaveRepetition, 1);
	services->setPixelShaderConstant("RefractionFactor", &m_RefractionFactor, 1);
	float fUnderWater = (m_smgr->getActiveCamera()->getPosition().Y < m_waternode->getPosition().Y) ? 1.0f : 0.0f;
	services->setPixelShaderConstant("UnderWater", &fUnderWater, 1);
}
Header file CReflectedWater.h:

Code: Select all

//
// Reflected Water.
// sio2 'at' users.sourceforge.net
// Based on .NET code by DeusXL (Irrlicht forum)
//

#ifndef _CREFLECTEDWATER_H
#define _CREFLECTEDWATER_H

#include <irrlicht.h>

using namespace irr;

class CReflectedWater : public video::IShaderConstantSetCallBack
{
public:
	//! constructor
	CReflectedWater(const irr::c8 *name, IrrlichtDevice *device, scene::ISceneManager* smgr, s32 id,
		f32 tileSize, s32 tileCount, core::dimension2di RenderTargetSize);

	//! destructor
	~CReflectedWater();

	void updateRendertarget(scene::ISceneManager* smgr);

	//! Returns type of the scene node

	virtual void OnSetConstants(video::IMaterialRendererServices* services, s32 userData);

	const irr::c8	*m_name;

	video::SColorf	m_AddedColor;
	video::SColorf	m_MultiColor;
	f32				m_WaveHeight;
	f32				m_WaveLength;
	f32				m_WaveSpeed;
	f32				m_WaveDisplacement;
	f32				m_WaveRepetition;
    f32				m_RefractionFactor;

	IrrlichtDevice			*m_device;
	scene::ISceneManager	*m_smgr;
	scene::ISceneNode		*m_waternode;
	scene::ICameraSceneNode *m_watercam;

	video::ITexture			*m_rt;
};

#endif
Shader Header file CReflectedWater_ShaderCode.h:

Code: Select all

//
// Reflected Water.
// sio2 'at' users.sourceforge.net
// Based on .NET code by DeusXL (Irrlicht forum)
//

#ifndef _CREFLECTEDWATER_SHADERCODE_H
#define _CREFLECTEDWATER_SHADERCODE_H

const irr::c8 WATER_VERTEX_GLSL[] = 
				"uniform float Time;\n" \
				"uniform float WaveHeight, WaveLength, WaveSpeed;\n" \
				"varying vec4 waterpos;\n" \
				"varying float addition;\n" \
				"void main()\n" \
				"{\n" \
				"	waterpos = ftransform();\n" \
				"	addition = (sin((gl_Vertex.x/WaveLength) + (Time * WaveSpeed / 10000.0))) +\n" \
				"              (cos((gl_Vertex.z/WaveLength) + (Time * WaveSpeed / 10000.0)));\n" \
                "	waterpos.y += addition * WaveHeight;\n" \
				"	gl_Position = waterpos;\n" \
				"}\n";
const irr::c8 WATER_FRAGMENT_GLSL[] = 
				"uniform sampler2D ReflectionTexture;\n" \
				"uniform vec4 AddedColor, MultiColor;\n" \
                "uniform float UnderWater, WaveDisplacement, WaveRepetition, RefractionFactor;\n" \
				"varying vec4 waterpos;\n" \
				"varying float addition;\n" \
				"void main()\n" \
				"{\n" \
				"	vec4 projCoord = waterpos / waterpos.w;\n" \
				"	projCoord += vec4(1.0);\n" \
				"	projCoord *= 0.5;\n" \
				"	projCoord.x += sin(addition * WaveRepetition) * (WaveDisplacement / 1000.0);\n" \
				"	projCoord.y += cos(addition * WaveRepetition) * (WaveDisplacement / 1000.0);\n" \
				"	projCoord = clamp(projCoord, 0.001, 0.999);\n" \
				"	if(UnderWater == 0.0)\n" \
				"		projCoord.y = 1.0 - projCoord.y;\n" \
				"	vec4 refTex = texture2D(ReflectionTexture, vec2(projCoord));\n" \
				"	refTex = (refTex + AddedColor) * MultiColor;\n" \
                "	gl_FragColor = refTex;\n" \
                "	if(UnderWater == 1.0)\n" \
                "	    gl_FragColor *= (MultiColor / 1.1);\n" \
                "   gl_FragColor.a = RefractionFactor;" \
				"}\n";
const irr::c8 WATER_HLSL[] =
                "uniform float Time;\n" \
                "float4x4 mWorldViewProj;\n" \
                "float WaveHeight, WaveLength, WaveSpeed;\n" \
                "float4 AddedColor, MultiColor;\n" \
                "float UnderWater, WaveDisplacement, WaveRepetition, RefractionFactor;\n" \
                "struct VS_OUTPUT\n" \
                "{\n" \
                "    float4 Position : POSITION;\n" \
                "    float4 Diffuse : COLOR0;\n" \
                "    float2 TexCoord : TEXCOORD0;\n" \
                "};\n" \
                "VS_OUTPUT vertexMain( in float4 vPosition : POSITION,\n" \
                "                      in float3 vNormal : NORMAL,\n" \
                "                      float2 texCoord : TEXCOORD0 )\n" \
                "{\n" \
                "    VS_OUTPUT Output;\n" \
                "    Output.Position = mul(vPosition, mWorldViewProj);\n" \
                "    float addition = (sin((vPosition.x/WaveLength) + (Time * WaveSpeed / 10000.0))) +\n" \
                "                     (cos((vPosition.z/WaveLength) + (Time * WaveSpeed / 10000.0)));\n" \
                "    Output.Position.y += addition * WaveHeight;\n" \
                "    Output.Diffuse = float4(addition, addition, addition, addition);\n" \
                "    Output.TexCoord = Output.Position / Output.Position.w;\n" \
                "    return Output;\n" \
                "}\n" \
                "struct PS_OUTPUT\n" \
                "{\n" \
                "    float4 RGBColor : COLOR0;\n" \
                "};\n" \
                "texture ReflectionTexture;\n" \
                "sampler MySampler = sampler_state\n" \
                "{\n" \
                "    Texture = ReflectionTexture;\n" \
                "    AddressU = CLAMP;\n" \
                "    AddressV = CLAMP;\n" \
                "};\n" \
                "PS_OUTPUT pixelMain( float2 TexCoord : TEXCOORD0,\n" \
                "                     float4 Position : POSITION,\n" \
                "                     float4 Diffuse : COLOR0 )\n" \
                "{\n" \
                "    PS_OUTPUT Output;\n" \
                "    float2 projCoord = TexCoord;\n" \
                "    float addition = Diffuse.r;\n" \
                "    projCoord += float2(1.0, 1.0);\n" \
                "    projCoord *= 0.5;\n" \
                "    projCoord.x += sin(addition * WaveRepetition) * (WaveDisplacement / 1000.0);\n" \
                "    projCoord.y += cos(addition *WaveRepetition) * (WaveDisplacement / 1000.0);\n" \
                "    if(UnderWater == 1.0)\n" \
                "        projCoord.y = 1.0 - projCoord.y;\n" \
                "    projCoord = clamp(projCoord, 0.001, 0.999);\n" \
                "    float4 refTex = tex2D(MySampler, projCoord);\n" \
                "    refTex = (refTex + AddedColor) * MultiColor;\n" \
                "    Output.RGBColor = refTex;\n" \
                "    if(UnderWater == 1.0)\n" \
                "        Output.RGBColor *= (MultiColor / 1.1);\n" \
                "    Output.RGBColor.a = RefractionFactor;\n" \
                "    return Output;\n" \
                "}";
const irr::c8 CLAMP_VERTEX_GLSL[] = 
				"varying float cutoff;\n" \
				"void main()\n" \
				"{\n" \
				"	cutoff = gl_Vertex.y;\n" \
				"	gl_Position = ftransform();\n" \
				"	gl_TexCoord[0] = gl_MultiTexCoord0;\n" \
				"}\n";
const irr::c8 CLAMP_FRAGMENT_GLSL[] = 
				"uniform sampler2D DiffuseMap, DetailMap;\n" \
                "uniform float WaterPositionY;\n" \
				"varying float cutoff;\n" \
				"void main()\n" \
				"{\n" \
				"	vec4 color = texture2D(DiffuseMap, gl_TexCoord[0].st) * 2.0 *\n" \
				"                texture2D(DetailMap, vec2(gl_TexCoord[0].x * 5.0, gl_TexCoord[0].y * 5.0));\n" \
                "	if(cutoff <= (WaterPositionY - 10.0))\n" \
				"		color.a = 0.0;\n" \
				"	else\n" \
				"		color.a = 1.0;\n" \
				"	gl_FragColor = color; \n" \
				"}\n";

const irr::c8 CLAMP_HLSL[] = 
                "uniform float Time;\n" \
                "float4x4 mWorldViewProj;\n" \
                "float WaterPositionY;\n" \
                "struct VS_OUTPUT\n" \
                "{\n" \
                "    float4 Position : POSITION;\n" \
                "    float4 Diffuse : COLOR0;\n" \
                "    float2 TexCoord : TEXCOORD0;\n" \
                "    float2 TexCoord1 : TEXCOORD1;\n" \
                "};\n" \
                "VS_OUTPUT vertexMain( in float4 vPosition : POSITION,\n" \
			    "                      in float3 vNormal : NORMAL,\n" \
			    "                      float2 texCoord : TEXCOORD0,\n" \
			    "                      float2 texCoord1 : TEXCOORD1)\n" \
                "{\n" \
                "    VS_OUTPUT Output;\n" \
                "    Output.Position = mul(vPosition, mWorldViewProj);\n" \
                "    Output.Diffuse = vPosition;\n" \
                "    Output.TexCoord = texCoord;\n" \
                "    Output.TexCoord1 = texCoord1;\n" \
                "    return Output;\n" \
                "}\n" \
                "struct PS_OUTPUT\n" \
                "{\n" \
                "    float4 RGBColor : COLOR0;\n" \
                "};\n" \
                "sampler2D DiffuseMap;\n" \
                "sampler2D DetailMap;\n" \
                "PS_OUTPUT pixelMain( float2 TexCoord : TEXCOORD0,\n" \
			    "                     float2 TexCoord1 : TEXCOORD1,\n" \
			    "                     float4 Position : POSITION,\n" \
			    "                     float4 Diffuse : COLOR0 )\n" \
                "{\n" \
                "    PS_OUTPUT Output;\n" \
                "    float4 color = tex2D(DiffuseMap, TexCoord) * 2.0f *\n" \
		        "                   tex2D(DetailMap, float2(TexCoord1.x * 5.0f, TexCoord1.y * 5.0f));\n" \
                "    if(Diffuse.y <= WaterPositionY)\n" \
                "        color.a = 0.0;\n" \
                "    else\n" \
                "        color.a = 1.0;\n" \
                "    Output.RGBColor = color;\n" \
                "    return Output;\n" \
                "}";

#endif
Code for the converted demo, WaterDemo.cpp:

Code: Select all

//
// Reflected Water Demo.
// sio2 'at' users.sourceforge.net
// Converted to C++ from the .NET code written by DeusXL (Irrlicht forum)
//

#include <stdio.h>
#include <iostream>
#include <wchar.h>
#include <irrlicht.h>

#include "CReflectedWater.h"

using namespace irr;

using namespace irr::core;
using namespace irr::video;
using namespace irr::scene;

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

IrrlichtDevice* _device = 0;
bool _bExit = false;

class CMainOnSetConstants : public irr::video::IShaderConstantSetCallBack
{
public:
	virtual void OnSetConstants(irr::video::IMaterialRendererServices* services, s32 userData)
	{
		float fVal;
		SColorf col(0.0f,0.0f,0.0f,0.0f);
		if (userData == 1) {
			fVal = 5000000.0f;
			services->setPixelShaderConstant("Radius", &fVal, 1);
			services->setPixelShaderConstant("Ambient", reinterpret_cast<f32*>(&col), 4);
			fVal = 0.0f;
			services->setPixelShaderConstant("Texture", &fVal, 1);
		}
		fVal = 5000000.0f;
		services->setPixelShaderConstant("range", &fVal, 1);
		fVal = 0.0f;
		services->setPixelShaderConstant("decalMap", &fVal, 1);
		fVal = 1.0f;
		services->setPixelShaderConstant("heightMap", &fVal, 1);
	};
};

class CEventReceiver : public IEventReceiver
{
	bool OnEvent(const SEvent &Event)
	{
		if ((Event.EventType == irr::EET_KEY_INPUT_EVENT) &&
			Event.KeyInput.PressedDown && (Event.KeyInput.Key==KEY_ESCAPE))
		{
			_bExit = true;
			return true;
		}
		return false;
	}
};

int main()
{
	char i;

	// ask user for driver

	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");

	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_SOFTWARE2;break;
		case 'f': driverType = video::EDT_NULL;     break;
		default: return 1;
	}

	CEventReceiver *_EventReceiver = new CEventReceiver();

	_device = createDevice(driverType, core::dimension2di(800, 600),
		16, false, false, false, _EventReceiver);

	video::IVideoDriver* _driver = _device->getVideoDriver();
	scene::ISceneManager* _scene = _device->getSceneManager();

	_device->getFileSystem()->changeWorkingDirectoryTo("medias");
	_device->getCursorControl()->setVisible(false);

	_scene->addCameraSceneNodeFPS(0, 100.0f, 1000.0f); //, false);
	_scene->getActiveCamera()->setPosition(core::vector3df(0, 400, -5000));
	float fFar = _scene->getActiveCamera()->getFarValue();
	_scene->getActiveCamera()->setFarValue(fFar *= 1000); // TODO: revise this

	_scene->setShadowColor(video::SColor(150,0,0,0));

	scene::IMesh *castlemesh = _scene->getMesh("castl3ds/a3dcastl.3ds")->getMesh(0);
	scene::ISceneNode *castlenode = _scene->addMeshSceneNode(castlemesh);
	castlenode->setMaterialFlag(video::EMF_LIGHTING, false);
	castlenode->setMaterialFlag(video::EMF_BACK_FACE_CULLING, false);
	castlenode->setScale(core::vector3df(10, 10, 10));
	SMaterial m = castlenode->getMaterial(1);
	m.MaterialType = EMT_SOLID;
	m.Texture1 = _driver->getTexture("castl3ds/casstne2.bmp");
	m = castlenode->getMaterial(2);
	m.MaterialType = EMT_SOLID;
	m.Texture1 = _driver->getTexture("castl3ds/caswd2.bmp");
	m.Texture2 = _driver->getTexture("castl3ds/caswd2.bmp");

	CMainOnSetConstants *_MainOnSetConstants = new CMainOnSetConstants;

	int ppxshading = _driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles(
		"ppxshading.vert", "main", irr::video::EVST_VS_1_1, "ppxshading.frag", "main",
		irr::video::EPST_PS_1_1, _MainOnSetConstants, EMT_SOLID, 1);
	core::array<IAnimatedMeshSceneNode*> tinies;
	for (int i = -1000; i <= 1000; i += 500)
	{
		IAnimatedMesh *tinymesh = _scene->getMesh("tiny/tiny.x");
		IAnimatedMeshSceneNode *tiny = _scene->addAnimatedMeshSceneNode(tinymesh);
		tiny->setMaterialFlag(video::EMF_LIGHTING, false);
		tiny->setAnimationSpeed(5000);
		tiny->setMaterialType((E_MATERIAL_TYPE)ppxshading);
		tiny->setPosition(vector3df((float)i, 300, -2200));
		ISceneNode *hand = tiny->getXJointNode("Bip01_L_Hand");
		IMesh *clevemesh = _scene->getMesh("cleve3ds/a3dcleve.3ds")->getMesh(0);
		ISceneNode *clevenode = _scene->addMeshSceneNode(clevemesh, hand, -1);
		clevenode->setMaterialFlag(video::EMF_LIGHTING, false);
		clevenode->setScale(vector3df(5, 5, 5));
		clevenode->setRotation(vector3df(0, 20, 90));
		clevenode->setPosition(vector3df(70, 0, -40));
		clevenode->setMaterialType((E_MATERIAL_TYPE)ppxshading);
		hand = tiny->getXJointNode("Bip01_R_Hand");
		clevemesh = _scene->getMesh("cleve3ds/a3dcleve.3ds")->getMesh(0);
		clevenode = _scene->addMeshSceneNode(clevemesh, hand, -1);
		clevenode->setMaterialFlag(video::EMF_LIGHTING, false);
		clevenode->setScale(vector3df(5, 5, 5));
		clevenode->setRotation(vector3df(0, 160, 90));
		clevenode->setPosition(vector3df(70, 0, 40));
		clevenode->setMaterialType((E_MATERIAL_TYPE)ppxshading);
		tinies.push_back(tiny);
	}
	for (int i = -1000; i <= 1000; i += 500)
	{
		IAnimatedMesh *tinymesh = _scene->getMesh("dwarf/Dwarf.x");
		IAnimatedMeshSceneNode *tiny = _scene->addAnimatedMeshSceneNode(tinymesh);
		tiny->setMaterialFlag(video::EMF_LIGHTING, false);
		tiny->setAnimationSpeed(15);
		tiny->setMaterialType((E_MATERIAL_TYPE)ppxshading);
		tiny->setPosition(vector3df((float)i, 50, -4000));
		tiny->setRotation(vector3df(0, 180, 0));
		tiny->setScale(vector3df(7, 7, 7));
		tinies.push_back(tiny);
	}


	int parallax = _driver->getGPUProgrammingServices()->addHighLevelShaderMaterialFromFiles(
		"opengl2.vert", "main", EVST_VS_1_1, "opengl2.frag", "main",
		EPST_PS_1_1, _MainOnSetConstants, EMT_SOLID, 0);
	IMesh *plane = _scene->addHillPlaneMesh("plane", dimension2df(6000, 6000), dimension2di(10, 10),
										 0, 0.0f, dimension2df(0, 0), dimension2df(100, 100))->getMesh(0);
	plane = _scene->getMeshManipulator()->createMeshWithTangents(plane);
	ISceneNode *parallaxplane = _scene->addMeshSceneNode(plane); //, null, -1);
	parallaxplane->setMaterialFlag(EMF_LIGHTING, false);
	parallaxplane->setMaterialTexture(0, _driver->getTexture("rockwall.bmp"));
	parallaxplane->setMaterialTexture(1, _driver->getTexture("rockwall_height.bmp"));
	parallaxplane->setMaterialType((E_MATERIAL_TYPE)parallax);

	CReflectedWater *water = new CReflectedWater("ReflectedWater", _device, _scene, -1, 180, 100, dimension2di(512,512));
	ISceneNode *waternode = water->m_waternode;
	waternode->setPosition(vector3df(0, 50, -3000));
	water->m_WaveDisplacement /= 1.5f;
	water->m_WaveHeight *= 2.0f;
	water->m_WaveSpeed *= 5.0f;
	water->m_RefractionFactor = 0.51f;

	ISceneNode *sky = _scene->addSkyDomeSceneNode(_driver->getTexture("sky.png"), 10, 10, 1, 1.3, NULL);

	int lastfps = -1;
	while (_device->run() && !_bExit)
	{
		if (_device->isWindowActive())
		{
			//SViewFrustrum *frustrum = (SViewFrustrum *)_scene->getActiveCamera()->getViewFrustrum();
			//frustrum->recalculateBoundingBox();
			//Box3D fbox = frustrum.BoundingBox;
			_driver->beginScene(true, true, SColor(255,100,100,100));
			/*foreach (AnimatedMeshSceneNode t in tinies)
				if (t.TransformedBoundingBox.IntersectsWithBox(fbox))
					t.Visible = true;
				else
					t.Visible = false;*/

			water->updateRendertarget(_scene);
			_scene->drawAll();
			_driver->endScene();

			int fps = _driver->getFPS();
			if (fps != lastfps)
			{
				core::stringw str;
				str = L"Irrlicht .NET CP RPG (C++ Conversion) - FPS : ";
				str += fps;
				str += L" Polycount : ";
				str += (int)_driver->getPrimitiveCountDrawn();
				_device->setWindowCaption(str.c_str());
				lastfps = fps;
			}
		}
	}
	_device->drop();
}
Last edited by sio2 on Fri Nov 17, 2006 4:01 pm, edited 2 times in total.
BattleElf
Posts: 18
Joined: Sat Mar 04, 2006 10:55 am
Location: Brisbane, Australia

Post by BattleElf »

Is this a shader 2.0 effect? All I'm getting is bad texture effects, no water at all and the console repeatedly says:
Error: Parallax map renderer only supports vertices of type EVT_TANGENTS
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

Good point.

It's SM2.0 under DirectX and SM1.1 under OpenGL. If you select Direct3D9 and it does not work then try the OpenGL driver instead.

Or, you could alter the code to always use SM1.1. Take a look at:

Code: Select all

   if (edt == video::EDT_OPENGL) {
        dmat = gpu->addHighLevelShaderMaterial(
         WATER_VERTEX_GLSL, "main", video::EVST_VS_1_1,
       WATER_FRAGMENT_GLSL, "main", video::EPST_PS_1_1,
       this, video::EMT_TRANSPARENT_ALPHA_CHANNEL, 0);
   } else {
        dmat = gpu->addHighLevelShaderMaterial(
         WATER_HLSL, "vertexMain", video::EVST_VS_2_0,
       WATER_HLSL, "pixelMain", video::EPST_PS_2_0,
       this, video::EMT_TRANSPARENT_ALPHA_CHANNEL, 2);
   } 
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

I just double-checked by taking the code from this page and compiling it.

It seems that the Irrlicht code in the Subversion repository has changed to break this app in two ways:

1.

Code: Select all

class CEventReceiver : public IEventReceiver
{
   bool OnEvent(const SEvent &Event) 
should now be:

Code: Select all

class CEventReceiver : public IEventReceiver
{
	bool OnEvent(SEvent Event)
2. The parallax error message that you mention comes up with the Direct3D driver (although it does not with the OpenGL driver). I'll have to look at the Irrlicht source to see what's been changed...
BattleElf
Posts: 18
Joined: Sat Mar 04, 2006 10:55 am
Location: Brisbane, Australia

Post by BattleElf »

I had picked up that CEventReceiver error but forgot to mention it.

I changed the directx to 1.1 but it's still not working properly with either DirectX or OpenGL. A screenshot of it running under OpenGL is below. The DirectX driver runs the same except it doesn't have the reflection at all.

Image
BattleElf
Posts: 18
Joined: Sat Mar 04, 2006 10:55 am
Location: Brisbane, Australia

Post by BattleElf »

Ahh, I managed to get a look at the console before it gets spammed by the EVT_TANGENTS error. The below is what I get with the DirectX choice, I don't get any shader errors with OpenGL.

HLSL vertex shader compilation failed:
(1): error X3000: syntax error: unexpected token 'vec4'

HLSL vertex shader compilation failed:
(2): error X3000: syntax error: unexpected token 'vec3'

HLSL pixel shader compilation failed:
(48): warning X4702: complement opportunity missed because input result WAS clamped from 0 to 1
(45): error X4513: cannot perform dependent texture read which in any way is based on color inputs
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

The original demo doesn't allow you to choose drivers - it starts fullscreen in OpenGL. I can now see why. :lol: The demo isn't really set up for Direct3D; it loads in some GLSL shaders and doesn't have any HLSL alternative for Direct3D.

Having said that, the original .NET demo runs OK for me, and the converted code does runs OK in OpenGL (although there's some 3ds error in Irrlicht that stops the castle texture from loading).
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

I've edited the original posting to point out that the demo is not very Direct3D friendly. There's nothing stopping anyone messing around with it and getting it to work with D3D, though.

I recently posted another code snippet which uses the same Reflected Water code, and this demo should work in D3D. :wink: It's the standard PerPixelLighting demo but with a layer of reflective water (so no extra media files should be needed).

Snippet here:
http://irrlicht.sourceforge.net/phpBB2/ ... hp?t=16993
BattleElf
Posts: 18
Joined: Sat Mar 04, 2006 10:55 am
Location: Brisbane, Australia

Post by BattleElf »

Ok, well it's probably to do with my video card then because the original .NET version displays the same as the screenshot I posted above.
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

BattleElf wrote:Ok, well it's probably to do with my video card then because the original .NET version displays the same as the screenshot I posted above.
Out of interest, what video card do you have?
BattleElf
Posts: 18
Joined: Sat Mar 04, 2006 10:55 am
Location: Brisbane, Australia

Post by BattleElf »

It's a Radeon 9100 IGP and it's a real pain because I can't get the Catalyst drivers to identify it properly so I've got Omega drivers loaded.
sio2
Competition winner
Posts: 1003
Joined: Thu Sep 21, 2006 5:33 pm
Location: UK

Post by sio2 »

BattleElf wrote:It's a Radeon 9100 IGP and it's a real pain because I can't get the Catalyst drivers to identify it properly so I've got Omega drivers loaded.
The "Card Caps" spreadsheet from the DirectX SDK states that the 9100 IGP is VS1.1 and PS1.4, so the OpenGL version should work, in theory.

The spreadsheet also list that card as "DX8" level, so I wouldn't expect much of it. I guess Oblivion and Vista are out. :wink:
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

I've been working on a new water scene node for IrrSpintz. I like the screenshots for this. I'm gonna try to get it working with SVN Irrlicht and if I can, I can fix the DX HLSL shaders.
Image
DeusXL
Posts: 114
Joined: Sun Mar 14, 2004 9:37 am
Contact:

Post by DeusXL »

Nice, really nice conversion !

Please, if anyone modify the shaders or add something special, send me the mod on my private messenger, I would be glad to improve my scene node too (and I can't read all the time all the posts unfortunately :()
Irrlicht .NET complete and Cross Platform Wrapper
The kid on my avatar wrote:A painless lesson is one without any meaning
Spintz
Posts: 1688
Joined: Thu Nov 04, 2004 3:25 pm

Post by Spintz »

Works in DX for me, only problem is a stretching artifact in the reflection around the screen edge. I'll see if I can fix it...

Here's SS of what I'm talking about -

Image
Image
Post Reply