Water Reflections in DX8

Started by
5 comments, last by Steve_Segreto 4 years, 7 months ago

hey guys,

i have a problem over here with vertex shaders and going to need some professional help, so i thought i create a thread here.

i just decided to work this feature out for me, 2 days ago. so please dont expect me to have any experience in programming D3D.

i am trying to work this out on my own as good as i can, but i would really appreciate if someone could help me a bit or give me a push in the right direction.

i am paying for the solution, so you won't waste your time, if you decide to join me on this case.

 

but ok, lets start:

first of all, you have to know that i am editing a very old game, which is using Direct X 8. the water in this game is basically a simple plane, which is using a normal texture projected onto it.

so basically its just a plane with a texuture, that is initializing a alpha state for the texture, so you can look through the water ingame.

no shadows, no reflections, no animations yet. my first goal is to get the inverseViewMatrix working, to make at least the shadows of the world appear in the water.

so, here's the code of the actual render state of the water:

Spoiler


void LoadWaterMaterial()
{
	char buf[256];
	for (int i = 0; i < 30; ++i)
	{
		sprintf(buf, "C:/test/water/%water_1d.dds", i+1);
		WaterInstances[i].SetImagePointer((CGraphicImage *) CResourceManager::Instance().GetResourcePointer(buf));
	}
}

void RenderWater()
{
	// Saving Render State
	D3DXMATRIX TransformTextureToWater;
	
	STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
	STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	STATEMANAGER.SaveRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
	STATEMANAGER.SaveRenderState(D3DRS_COLORVERTEX, TRUE);

	STATEMANAGER.SetTexture(0, WaterInstances[((ELTimer_GetMSec() / 70) % 30)].GetTexturePointer()->GetD3DTexture());

	D3DXMatrixScaling(&TransformTextureToWater, WaterTextureCoordBase, -WaterTextureCoordBase, 0.0f);
	D3DXMatrixMultiply(&TransformTextureToWater, &InverseTheView, &TransformTextureToWater);
	
	STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &TransformTextureToWater);
	STATEMANAGER.SaveVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE);

	STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
	
	STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
	

	STATEMANAGER.SetTexture(1,NULL);
	STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
	STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
      
	// Restoring Render State
    STATEMANAGER.RestoreVertexShader();
	STATEMANAGER.RestoreTransform(D3DTS_TEXTURE0);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_MINFILTER);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_MAGFILTER);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_MIPFILTER);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSU);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSV);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXCOORDINDEX);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS);
	
	STATEMANAGER.RestoreRenderState(D3DRS_DIFFUSEMATERIALSOURCE);
	STATEMANAGER.RestoreRenderState(D3DRS_COLORVERTEX);
	STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
	STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
	STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
}

 

So, i noticed there's already something started for inversing the view ('&InverseTheView').

in another function, for setting the Inverse View and Shadow Matrices, its declared:


	InverseTheView = pCamera->GetInverseViewMatrix();
	
	D3DXVECTOR3 v3Target = pCamera->GetTarget();

	D3DXVECTOR3 v3LightEye(v3Target.x - 1.732f * 1250.0f,
						   v3Target.y - 1250.0f,
						   v3Target.z + 2.0f * 1.732f * 1250.0f);

	D3DXMatrixLookAtRH(&m_matLightView, &v3LightEye, &v3Target, &D3DXVECTOR3(0.0f, 0.0f, 1.0f));
	DynamicShadow = InverseTheView * LightView * DynamicShadowScale;

 

okay, so far so good. i tried to add the Inversed View to my Water rendering state:


void LoadWaterMaterial()
{
	char buf[256];
	for (int i = 0; i < 30; ++i)
	{
		sprintf(buf, "C:/test/water/%water_1d.dds", i+1);
		WaterInstances[i].SetImagePointer((CGraphicImage *) CResourceManager::Instance().GetResourcePointer(buf));
	}
}

void RenderWater()
{
	// Saving Render State
	D3DXMATRIX oldView = LightView; // Old light view
	D3DXMATRIX oldLight; // old light
	D3DXPLANE plane(0.0f, 1.0f, 0.0f, 0.0f);
	D3DXMATRIX invertMatrix;
	D3DXMatrixReflect(&invertMatrix, &plane);

	oldView = ms_matWorldView;
	D3DXMATRIX vue = oldView;
	D3DXMatrixMultiply(&vue, &vue, &invertMatrix); // Inverse view
	D3DXMatrixMultiply(&LightView, &LightView, &invertMatrix); // Inverse light


	STATEMANAGER.SaveRenderState(D3DRS_ZWRITEENABLE, FALSE);
	STATEMANAGER.SaveRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	STATEMANAGER.SaveRenderState(D3DRS_STENCILENABLE, true);
	STATEMANAGER.SaveRenderState(D3DRS_STENCILFUNC, D3DCMP_ALWAYS);
	STATEMANAGER.SaveRenderState(D3DRS_STENCILREF, 0x1);
	STATEMANAGER.SaveRenderState(D3DRS_STENCILMASK, 0xffffffff);
	STATEMANAGER.SaveRenderState(D3DRS_STENCILWRITEMASK, 0xffffffff);
	STATEMANAGER.SaveRenderState(D3DRS_STENCILZFAIL, D3DSTENCILOP_KEEP);
	STATEMANAGER.SaveRenderState(D3DRS_STENCILFAIL, D3DSTENCILOP_KEEP);
	STATEMANAGER.SaveRenderState(D3DRS_STENCILPASS, D3DSTENCILOP_REPLACE);
	STATEMANAGER.SaveRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
	STATEMANAGER.SaveRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1);
	STATEMANAGER.SaveRenderState(D3DRS_COLORVERTEX, TRUE);
	STATEMANAGER.SaveRenderState(D3DRS_SPECULARENABLE, TRUE);
	STATEMANAGER.SaveRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_COLOR2);

	/// Reflection

	D3DXMATRIX reflection = vue;
	D3DXMatrixScaling(&reflection, m_fWaterTexCoordBase, -m_fWaterTexCoordBase, 0.0f);
	STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &reflection);
	LPDIRECT3DTEXTURE9 textureEau = m_WaterInstances[((ELTimer_GetMSec() / 30) % 250)].GetTexturePointer()->GetD3DTexture();

	STATEMANAGER.SetFVF(D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR | D3DFVF_TEX0 | D3DFVF_TEX1);

	STATEMANAGER.SetTexture(0, textureEau);

	STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_PROJECTED);
	STATEMANAGER.SaveSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_MIRROR);
	STATEMANAGER.SaveSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP);
	STATEMANAGER.SaveSamplerState(0, D3DSAMP_ADDRESSW, D3DTADDRESS_CLAMP);

	STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);

	// Start of Water
	
	STATEMANAGER.SetTexture(0, WaterInstances[((ELTimer_GetMSec() / 70) % 30)].GetTexturePointer()->GetD3DTexture());

	D3DXMatrixScaling(&TransformTextureToWater, WaterTextureCoordBase, -WaterTextureCoordBase, 0.0f);
	D3DXMatrixMultiply(&TransformTextureToWater, &InverseTheView, &TransformTextureToWater);
	
	STATEMANAGER.SaveTransform(D3DTS_TEXTURE0, &TransformTextureToWater);
	STATEMANAGER.SaveVertexShader(D3DFVF_XYZ|D3DFVF_DIFFUSE);

	STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEPOSITION);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_MINFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP);
	STATEMANAGER.SaveTextureStageState(0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP);
	
	STATEMANAGER.SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE);
	STATEMANAGER.SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
	

	STATEMANAGER.SetTexture(1,NULL);
	STATEMANAGER.SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
	STATEMANAGER.SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE);
      
	// Restoring Render State
    STATEMANAGER.RestoreVertexShader();
	STATEMANAGER.RestoreTransform(D3DTS_TEXTURE0);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_MINFILTER);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_MAGFILTER);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_MIPFILTER);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSU);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_ADDRESSV);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXCOORDINDEX);
	STATEMANAGER.RestoreTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS);
	
	STATEMANAGER.RestoreRenderState(D3DRS_DIFFUSEMATERIALSOURCE);
	STATEMANAGER.RestoreRenderState(D3DRS_COLORVERTEX);
	STATEMANAGER.RestoreRenderState(D3DRS_ZWRITEENABLE);
	STATEMANAGER.RestoreRenderState(D3DRS_ALPHABLENDENABLE);
	STATEMANAGER.RestoreRenderState(D3DRS_CULLMODE);
}

The Output is, i would say strange. its flickering, framing between black and gray color. but its not inversing the view.

Does it have something to do, with clipping the frustum view?

 

I really do not have any clue how to work with this properly. i would really appreciate if someone here gives me the push in the right direction, as mentioned.

you'll get rewarded, too!

 

thanks for reading and best regards

Advertisement

You really should try a graphics frame capture debugger like Pix to be sure your issue is what you think it is.

From that last snippet of code, if you comment this line out, does that fix your render from flickering?


D3DXMatrixMultiply(&TransformTextureToWater, &InverseTheView, &TransformTextureToWater);

Have you tried reversing the order of the matrix multiply?

 

 

 

thanks for your reply. i will try it when i am at home. i managed to work a little further yesterday, but still have trouble with getting this to work.

I added D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR to the SaveTextureStageState and got a pretty accurate result.

its starting to reflect something, but gives me wrong output. i think there's something missing for projecting the scene back onto the plane (inverse).

On 9/10/2019 at 8:13 AM, Steve_Segreto said:

You really should try a graphics frame capture debugger like Pix

I don't think Pix or RenderDoc support DX8.

Aether3D Game Engine: https://github.com/bioglaze/aether3d

Blog: http://twiren.kapsi.fi/blog.html

Control

ok, basically i managed to get some reflection, as i've posted before. so, the vector is already given, i just had to add those statements to the render part, to get this kinda "reflection". but the problem at the moment is, the water plane can't recognize the world environment. thats because there are still missing code parts. i think the right way in this case would be the cube mapping option. 

basically the water looks ingame, like something would mirror in it. there's like a white fade effect going over the plane, every few seconds. 

also i looked through the source and found some functions that are rendering the specular texture part for the game. they've been using D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR  also for this function, which causes a mirror-like effect ingame.

so basically i am on the right track, i think. but still gonna need some help, so please - if you ever worked with this DX rev. contact me! it won't be a waste of time, as mentioned before.

Link to Forsaken Online Water Shader (could be useful, also using DX8)

6 hours ago, bioglaze said:

I don't think Pix or RenderDoc support DX8.

It’s been almost 15 years since I last worked with D3D8, but at that time it was really trivial to convert even a large commercial program from 8 to 9, might be worth the effort for the better tools. If not you can try things like this: http://jrfonseca.blogspot.com/2008/07/tracing-d3d-applications.html?m=1

This topic is closed to new replies.

Advertisement