Sign in to follow this  

Water projected reflections

This topic is 4747 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I´ve been trying to render my water using projected texture for reflections. I have already readed Yann's article, and lots of topics discussing water reflections. But my problem is: is there a way to do it without any pixel shaders? By the way, I´m using DirectX and a HLSL Vertex Shader. Thanks!

Share this post


Link to post
Share on other sites
Basic projected water doesn't require anything per pixel at all, except for a simple decal texturing. Everything is done in the vertex shader.

However, if you want to increase realism, it will be difficult to do it without at least some basic per pixel shading. Fresnel and refractions will still look OK without a complex pixel shader (just a simple blend), most operations can be kept in the per vertex. But as soon as bumpmaps or perpixel reflections come into the equation, there's no way around a pixel shader.

Share this post


Link to post
Share on other sites
I understand the necessity of the pixel shader. But I have to make it work in older machines, and the pixel shader cannot be emulated by software as the vertex shader. I have do deal with it because the game prototype will be in a (sort of) contest in the college I study.

I didn't understand what you mean with "except for a simple decal texturing".
In your article you do use a pixel shader for projection (text2Dproj).

How can I actually do the reflection without pixel shaders?
(some code sample will help)


Thanks for replying!

Share this post


Link to post
Share on other sites
You mean the refleciton itself? Just refleciting doesn't require pixel shaders at all. All that shaders will do for you, in a rough explanation, is allow you to perturb the texture UV coords at fragment level. It won't do reflection for you.

First, you need to get the reflected image of your scene into a texture. Virtually any videocard in use today can do that, even old stuff like the TNT. Calculate the reflected camera matrix, clip your world at the water plane, and render it to a texture (google for "render to texture" and directX, you'll gett awesome resources on how to do it).

Second, you need to project the said texture on the water. Again, google for "projective mapping" to get good resources on how to do it. This can be done without problems at vertex level.

By now you'll have a nice flat reflective water mirror. No waves. There are various ways to simulate waves, and most of them can be done at vertex level. When you get your waves running, you just perturb the UV coords at vertex-level based on the vertex normal.

Share this post


Link to post
Share on other sites
I already have my waves simulation. I'm using the FFT approach.

And already rendered the reflection to my texture too.
My problem is just projecting it.

If you read Yann's article you will se that he uses vertex and pixel shaders for projecting the texture. How can I do it without the pixel shaders?

Share this post


Link to post
Share on other sites
Quote:
Original post by lgcosta
I didn't understand what you mean with "except for a simple decal texturing".
In your article you do use a pixel shader for projection (text2Dproj).

The pixel "shaders" in this article can't really be called shaders, since they are extremely basic. Everything important is really done in the vertex shader. tex2Dproj is just like a normal texture lookup, but with projection (ie. with enabled homogeneous divide). Every standard fixed function pipeline can do that, however old it might be. You just have to load the projective matrix into the texture matrix of the appropriate texture stage, and enable the D3DTTFF_PROJECTED setting, so that D3D does the homogeneous divide on the texture coordinates.

That's all, no real pixel shader needed for such basic water.

Share this post


Link to post
Share on other sites
Sorry for so many questions, but I can´t make it work. I´ve already readed all the topics about this, where Yann talk to Mephs and Paul7.
I don´t know where I´m wrong.

What I´m doing is:


// Gets the projection and view matrix.
device->GetTransform(D3DTS_PROJECTION, &matProj);
device->GetTransform(D3DTS_VIEW, &matView);

// Creates the reflection plane.
D3DXVECTOR3 vPoint(0,0,0);
D3DXVECTOR3 vNormal(0,1,0);
D3DXPlaneFromPointNormal( &plane, &vPoint, &vNormal );

// Reflect the plane and saves the new view matrix.
D3DXMatrixReflect(&matReflect, &plane);
D3DXMatrixMultiply(&matView, &matReflect, &matView);
device->SetTransform(D3DTS_VIEW, &matView);

// Calculates the projective texture mapping matrix.
D3DXMatrixMultiply(&m_pReflectTexMatrix, &matView, &matProj);
D3DXMatrixMultiply(&m_pReflectTexMatrix, &remap, &m_pReflectTexMatrix);

// RENDER TO TEXTURE HERE



I'm sure that the rendered reflection is ok, but I'm not 100% sure about the projective texture matrix.

So.. when I´m rendering the water I use:


// Sets the tranformation matrix.
device->SetTransform(D3DTS_TEXTURE0, &m_pReflectTexMatrix);
device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS,
D3DTTFF_COUNT4 | D3DTTFF_PROJECTED );

// Set texture.
device->SetTexture(0, this->m_pReflectTexture);

// Set FVF
device->SetFVF(WATER_VERTEX_FVF);

// RENDER THE WATER



By the way, my FVF has 2 coordinates for the texture. Is that right?

And my VS does:


// sets the output vertex position
Out.vPos = mul(matViewProj, In.vPos);

// map the texture
// mapReflect is the m_pReflectTexture in VS.
Out.vTexture = mul(matReflect, In.vPos);

return Out;



As I´m using the Directx D3DTTFF_PROJECTED I suppose I don´t need pixel shaders for doing the homogeneous divide, right?

There is a point in other topics wich I didn´t understand. It´s about the remapping matrix. How do I know if my remapping matrix has to be the same matrix of Yann's article (transposed for dx)?
I didn´t understand how the range of the coordinates will be from -1 to 1.

Any obvious mistake?

Share this post


Link to post
Share on other sites
Think I can see one thing your doing wrong.

What you need to do it render the scene to the texture with the reflected view matrix, then render the scene again with an unreflected view matrix and calculate the projective texture mapping matrix here, you appear to be calculating this using the reflected view matrix.

Also I think you may need more than 2 texture coordinates, not 100% sure though dont know how it works out of shaders. I just use the whole vertex for my texture coordinates (X Y Z W).

Dont really get what your using your vertex shaders for.

As for the remap matrix this is what I use in DirectX:


remap_matrix._11=0.5;
remap_matrix._12=0;
remap_matrix._13=0;
remap_matrix._14=0;
remap_matrix._21=0;
remap_matrix._22=-0.5;
remap_matrix._23=0;
remap_matrix._24=0;
remap_matrix._31=0;
remap_matrix._32=0;
remap_matrix._33=0.5;
remap_matrix._34=0;
remap_matrix._41=0.5;
remap_matrix._42=0.5;
remap_matrix._43=0.5;
remap_matrix._44=1.0;

Share this post


Link to post
Share on other sites
I tried changing the reflection matrix to be calculated with the unreflected view matrix, but nothing changed. I found in other posts Yann saying:

Quote:

The projective texturing is not very hard either, now that you got this thing working. It's basically the exact same matrix you used for rendering the RTT, only multiplied with your current projection matrix and an additional remapping matrix. Load that into the texture matrix of the texture unit you want to project from (is it also called texture matrix in D3D ? I think so), and feed the unit the same 3D vertex positions you used for rendering, only as texcoords this time.


I understood I need to use the reflected view matrix.
Anyway, my reflection now is the same when I use the reflected view matrix or the unreflected view matrix to get the transformation matrix.
I´ll put an screenshot as soon as my public domain server goes up.

I'm using the vertex shader because I do some water color calculation at vertex level too. But It´s disabled for now.

Share this post


Link to post
Share on other sites
Yeah thats what it sounds like from Yanns description, maybe thats why I have to negate one of the coordinates in the remapping matrix.

Screenshots will be helpful to see what results your actually getting.

Share this post


Link to post
Share on other sites
Quote:
Original post by lgcosta
By the way, my FVF has 2 coordinates for the texture. Is that right?

It doesn't matter, it will not even be used. The texture coordinate component of the vertex specification is ignored by the vertex shader for the projective stage, and can be dropped altogether (the texcoords are generated entirely within the shader).

Quote:
Original post by lgcosta
Quote:

The projective texturing is not very hard either, now that you got this thing working. It's basically the exact same matrix you used for rendering the RTT, only multiplied with your current projection matrix and an additional remapping matrix. Load that into the texture matrix of the texture unit you want to project from (is it also called texture matrix in D3D ? I think so), and feed the unit the same 3D vertex positions you used for rendering, only as texcoords this time.


I understood I need to use the reflected view matrix.

No. If you read single answers posted to a different thread, then you should take the context of that thread into account. Mephs had been using a separate reflection matrix in the first step, and got the multiplication order wrong. We fixed that and went on the the next one. From this context, I meant the unreflected view matrix by saying "matrix". Be careful to read the entire thread before assuming things in individual posts. But all that's explained in great detail in my water article.

Quote:
Original post by Paul7
Yeah thats what it sounds like from Yanns description, maybe thats why I have to negate one of the coordinates in the remapping matrix.

Actually, you have to negate the Y component of the remapping matrix in D3D, because D3D uses a different Y origin for textures. In OpenGL, (0,0) refers to the bottom left corner, while in D3D it referes to the top left one. It ultimately all depends on how you set up your view reference frame. Note that flipping the Y component is in no way a substitute for a proper reflection matrix in the RTT pass ! Using it as such a replacement can lead to very strange artifacts and incorrect reflections.

Share this post


Link to post
Share on other sites
Again, thanks for replying this. You have been extremely helpful clarifying all those details!

Now that you can see the screenshot and the code, do you have any ideia why is this happening? My water plane is that strange bluesh thing..

I´ve changed the calculation of the transformation matrix, but nothing changed.

Share this post


Link to post
Share on other sites
Well, now I think I´ve got something better.

Using the -0.5 in the _22 element of the remapping matrix (because of Yann's explanation), and calculating the transformation matrix with the untransformed view matrix. Also transposed the view * proj matrix:

// Calculates the projective texture mapping matrix.
D3DXMatrixMultiply(&m_pReflectTexMatrix, &matView, &matProj);
D3DXMatrixTranspose(&m_pReflectTexMatrix, &m_pReflectTexMatrix);
D3DXMatrixMultiply(&m_pReflectTexMatrix, &remap, &m_pReflectTexMatrix);

The screenshot:



It seems that when the texture is in left of the center of the screen, it gets some distortion.

Share this post


Link to post
Share on other sites
Dont see why you`d need to transpose your view projection matrix unless you`ve got them defined differently.

Other than that I`m really not too sure. If you want to send me your code I could have a bit of a look at it for you, Not that I know all that much about it but mite be able to spot something- PM me if you want me to and i`ll give you my email.

Share this post


Link to post
Share on other sites
Hey all! (working on LiSPSM shadows now, which funnily enough involves projecting shadows, and pulling my hair out too!!)

I guess by looking at your latest screenshot that the texture is being clamped at the edges (thats what the stretched and banded artifact appears to be). If the texture is being clamped, then I'd guess that the texture coordinates are becoming larger than 1 or smaller than 0, so I'd take a wild guess that your remap matrix still might not be correct.

As for transposing your view*projection matrix, I think that is necessary because the vertex and pixel shaders work in a different coordinate frame to DirectX, or something along those lines! Basically, once you have a matrix that works with DirectX when not using vertex shaders, it needs transposing to work if you do use shaders.


Anyways hope that points you in the right direction (and I'm hoping I've informed you correctly!!)

Cheers,

Steve

Share this post


Link to post
Share on other sites
I think Ive got it sorted for you.

Firstly the matter of the transposes The reason I dont need them is because the multiplications in the shader are the other way round.

So firstly if you remove following tranposes in your waterrender.cpp:


//In your void CWaterRender::SetShader() function

D3DXMatrixMultiply(&matViewProj, &matView, &matViewProj);
//D3DXMatrixTranspose(&matViewProj, &matViewProj);

//And in your CWaterRender::RenderReflection() function

D3DXMatrixMultiply(&m_pReflectTexMatrix, &matView, &matProj);
//D3DXMatrixTranspose(&m_pReflectTexMatrix, &m_pReflectTexMatrix);
D3DXMatrixMultiply(&m_pReflectTexMatrix, &m_pReflectTexMatrix, &remap);



then change the following lines in your shader to:


Out.vPos = mul(In.vPos,matViewProj );
Out.vTexture = mul(In.vPos, matReflect);



and the main problem thats causing your reflections to be messed up is:


//Before you had it as:

D3DXMatrixMultiply(&m_pReflectTexMatrix, &remap, &m_pReflectTexMatrix);

//And it should be:

D3DXMatrixMultiply(&m_pReflectTexMatrix, &m_pReflectTexMatrix, &remap);



This then gives you this:


When you press the arrow keys up and down it gets a bit messed up though. Does this rotate the camera or the water plane. But think thats a problem somewhere else.>

Share this post


Link to post
Share on other sites
Wow!!!
Thanks a lot man! I can´t believe that was such a mess!

The problem with the up and down arrows is that they are changing the world matrix. That´s just for test, a friend of mine is doing the input. :)

Anyway, thank you all. This topic was really clarifying for me!

Share this post


Link to post
Share on other sites

This topic is 4747 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this