The problem with connecting nVidia shader (Ocean.fx) to my own engine

Started by
1 comment, last by PolGraphic 13 years, 11 months ago
Hello. From the beginning I want to say that as far as the shaders are concerned, I'm a noob ;-) So please, take it into account, when you'll be posting answers. I wanted to connect my own 3D engine (based on DirectX 9) with the shader form nVidia website (as far as I know, the license gives permission to use it in both commercial and non-commercial projects). So I have downloaded the shader from http://developer.download.nvidia.com/shaderlibrary/packages/Ocean.fx.zip and loaded it to engine in not changed form. I wrote that in engine to set shader's parameters:

shaders[shaderIndex]->effect->SetMatrix("gWvpXf", worldViewProjectionMatrix);
shaders[shaderIndex]->effect->SetMatrix("gWorldXf", matWorld);
shaders[shaderIndex]->effect->SetMatrix("gViewIXf", matView);
D3DXMATRIX matWorldInverseTransponse;
D3DXMatrixInverse(&matWorldInverseTransponse, NULL, matWorld);
D3DXMatrixTranspose(&matWorldInverseTransponse, &matWorldInverseTransponse);
shaders[shaderIndex]->effect->SetMatrix("gWorldITXf", &matWorldInverseTransponse);
Textures:

D3DXCreateTextureFromFile(device, "waves2.dds", &texture);
shaders[shaderIndex]->effect->SetTexture("NormalTexture", texture);

D3DXCreateTextureFromFile(device, "CloudyHillsCubemap2.dds", &gEnvTexture);
shaders[shaderIndex]->effect->SetTexture("gEnvTexture", gEnvTexture);
And the time:

time_t czas;
time ( &czas );
clock_t time_elapsed;
float time_in_seconds;
int count;
time_elapsed = clock();
time_in_seconds = (float) time_elapsed / CLOCKS_PER_SEC;
shaders[shaderIndex]->effect->SetFloat("gTimer", time_in_seconds);
I do it every time before the render - I think it could be set once time, because that are e.g. the pointers to the matrix. But I have done it now that way to be sure, that it's not the reason of my problem. I haven't found the place to give to the shader the info about my scene light. It seems that the light is connected to the camera. I got that effect: The first thing I have noticed, was that the shader works the best with 'flat planes'. I have loaded that shader also to the Fx Composer, created there sth with the name 'plane' and on the left from that plane I have imported my surface (hardly speaking it was just the plane form 3ds max converted to .x file, so the simple triangles - I have experimented with the number of triangles for that plane, but the effect was the same): I think that I have made at least two mistakes. The first is the surface that I have assigned to the shader. On 'plane' form Fx Composer the shader works in the way that the borders are swaying and the whole water is 'flowing' with the crests etc. On my surface the borders are immovable and the water seems to flow in the established direction (more like the river, not the ocean - I have to add that it wasn't planed ;p ). But I can't just render the D3DXPLANE, can I? It's just the mathematical form to describe the surface, I don't know how to draw it in the other way, not drawing the two triangles in the render loop :/ So it's stupid, but I don't know how to draw 'flat plane'. The second thing is 'something more' ;p In the Fx Composer (the fragment on the left, bottom picture) and in my engine (top picture) I have set the shader on the identical object (my .x surface). But after all, in my engine it's looks decidedly worst. I haven't an idea from what it depend, but the lighting is changing dramatically in the relation with the camera movement (from 'too much light' to the 'to dark', but I can't get the 'good lighting'). Btw it's seems to be not only the issue of the strong of light. It's very possible that both of my mistakes are very simple to fix, but I don't have an experience to get the idea what to do now :/ [Edited by - PolGraphic on April 24, 2010 12:15:45 PM]
Advertisement
hey used the shader as well in my engine and you have to draw it on a vertice grid, the more polygons it has the smoother your waves.

i also had the same problems like you (looking weird in engine, looking good in composer). you just have to fiddle with some of the constants. i think it had to do with the world size of the plane (like composer plane is 1.0f in size and plane in my engine was size 1500.0f or something)

heres some code to create the plane

	int x, z, i;        //number of cells	zgrid = 50;	xgrid = 50;	float xo, zo, xs,zs;        //plane scale	xs=150.0f;	zs=150.0f;        //plane offset	xo=25.0f*xs-100.0f;	zo=25.0f*xs-100.0f;	// Vertexbuffer	device->CreateVertexBuffer	(		(xgrid+1) * (zgrid+1) * sizeof(vertex),		D3DUSAGE_WRITEONLY,		vertex::FVF_Flags,		D3DPOOL_MANAGED,		&vertexbuffer,		NULL	);	vertex *vertices;	vertices = new vertex[(xgrid+1)*(zgrid+1)];    vertexbuffer->Lock( 0, 0, (void**)&vertices, 0 );	for( z = 0, i = 0; z <= zgrid; z++)	{		for( x = 0; x <= xgrid; x++, i++)		{			vertices.pos.x	=	-xo + xs*x;			vertices.pos.y	=	0.0f;			vertices.pos.z	=	-zo + zs*z;			vertices.u		=	((float)x)/xgrid*((float)xs*0.1f); 			vertices.v		=	-((float)z)/zgrid*((float)zs*0.1f);		}	}    vertexbuffer->Unlock();	vertices = NULL;	// Indexbuffer	device->CreateIndexBuffer	(		6 * xgrid * zgrid * sizeof(unsigned short),		D3DUSAGE_WRITEONLY,		D3DFMT_INDEX16,		D3DPOOL_MANAGED,		&indexbuffer,		NULL	);	unsigned short *indices;	indexbuffer->Lock(0, 0, (void**)&indices, 0);	for( z = 0, i = 0; z < zgrid; z++)	{		for( x = 0; x < xgrid; x++, i+=6)		{			indices   = z		*	(xgrid+1)	+	x;			indices[i+1] = (z + 1)	*	(xgrid+1)	+	x;			indices[i+2] = (z + 1)	*	(xgrid+1)	+	x + 1;			indices[i+3] = z		*	(xgrid+1)	+	x;			indices[i+4] = (z + 1)	*	(xgrid+1)	+	x + 1;			indices[i+5] = z		*	(xgrid+1)	+	x + 1;		}	}	indexbuffer->Unlock();


and here a snippet of my header of the .fx. i only changed those tweakable parameters i think.

///////// TWEAKABLE PARAMETERS //////////////////float gBumpScale = 0.15;float gTexReptX = 8.0;float gTexReptY = 4.0;float gBumpSpeedX = -0.1;float gBumpSpeedY = 0.0;float gFresnelBias = 0.2;float gFresnelExp = 4.0;float gHDRMultiplier = 3.0;float3 gDeepColor = {0.0f, 0.0f, 0.1f};float3 gShallowColor = {0.0f, 0.3f, 0.4f};float3 gReflTint = {1.0f, 1.0f, 1.0f};float gKr <    string UIName = "Reflection Strength"; > = 1.0f;float gKWater <    string UIName = "Water Color Strength";   > = 1.0f;float gWaveAmp = 8.0f;float gWaveFreq = 0.0065;
Thanks a lot :)
It works well.

I still have some artifacts or sth like that on some part of surface, but it's nothing to compare with what it looks before (btw I can't fix them 'more'):



Once again - thanks.

This topic is closed to new replies.

Advertisement