Advertisement

Projective textures. Crispy or anyone? plz ^_^

Started by May 15, 2004 12:50 PM
4 comments, last by midori 20 years, 6 months ago
Hello there, the original post is located here: http://www.gamedev.net/community/forums/topic.asp?whichpage=2&pagesize=20&topic_id=124632 If anyone can help me, I would really appreciate it!! Ok, I have the reflective image saved onto a texture. Now, I need to project this to a water surface. To do this, I first need to do this?: // Setup texture coordinate equations GLfloat plane_s[] = { 1.f, 0, 0, 0 }; GLfloat plane_t[] = { 0, 1.f, 0, 0 }; GLfloat plane_r[] = { 0, 0, 1.f, 0 }; GLfloat plane_q[] = { 0, 0, 0, 1.f }; glMatrixMode(GL_MODELVIEW); glPushMatrix();glLoadIdentity(); glTexGenfv(GL_S, GL_EYE_PLANE, plane_s); glTexGenfv(GL_T, GL_EYE_PLANE, plane_t); glTexGenfv(GL_R, GL_EYE_PLANE, plane_r); glTexGenfv(GL_Q, GL_EYE_PLANE, plane_q); glPopMatrix(); So the plane_s and etc are the equations that define the texture coordinates? I''m not entirely sure about this. Next step is: glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR); glEnable(GL_TEXTURE_GEN_S); glEnable(GL_TEXTURE_GEN_T); glEnable(GL_TEXTURE_GEN_R); glEnable(GL_TEXTURE_GEN_Q); glMatrixMode(GL_TEXTURE); glPushMatrix(); glLoadIdentity(); glTranslatef(.5f, .5f, 0); glScalef(.5f, .5f, 1.f); gluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f); glMatrixMode(GL_MODELVIEW); ///////////////////////////////////////////////////////////// //(code by vincoof) Do I not need to bind the reflective texture before I code any of this? Also, we need to set the matrix so that the projector is projecting the image in the right place.. right? Is that done by gluPerspective(); followed by the glMatrixMode(GL_MODELVIEW); ?? Or am I supposed to calculate the matrix and do some matrix multiplication? So, if I do all this, and render the water surface, the reflective image will be projected onto the water surface? Am I supposed to take normals of the surface of the water? Phew! Sorry for the large amount of questions~~! If you have the time, would be able to answer some of the questions? Thanks a lot! (*^_^*) -Jennifer
I haven''t dealt with OpenGL for a while now, especially with projective texturing. However, having dug up some ages old code, you can have a look at this and maybe find it useful:

The header file:
class TMirrorSurface{	private:   	TOpenGLWindow* TargetWindow;      TVector3f Color;      float Transparency, Height;      std::vector<TVector3f*>Corners;      TOpenGLTextureContainer* RefTC;//NOTE: same as GLuint      GLTexture ReflectionTxID;      int TexSize;		GLfloat IdentityPlaneS[4];		GLfloat IdentityPlaneT[4];		GLfloat IdentityPlaneR[4];		GLfloat IdentityPlaneQ[4];   public:   	TMirrorSurface() {};      ~TMirrorSurface();		TMirrorSurface(TOpenGLWindow * pTargetWindow,      		TVector3f pColor, float pTransparency, int pTexSize,            float pHeight, std::vector<TVector3f*>pCorners);		//usage:		//1) Prepare()		//2) Draw reflected scene		//3) Capture()		//4) Draw real scene		//5) Create()		void Prepare();		void Capture();		void Create();};


The code file:
void TMirrorSurface::Prepare(){      TargetWindow->SetViewport(TexSize, TexSize);			glPushMatrix();      		glTranslatef(0, 2 * Height, 0);				glScalef(1.0f, -1.0f, 1.0f);		   	glEnable(GL_DEPTH_TEST);}void TMirrorSurface::Capture(){			glPopMatrix();	      RefTC->Bind(ReflectionTxID);			glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, TexSize, TexSize, 0);			glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);      TargetWindow->RestoreViewport();}#include "G_Error.h"#include "G_Externs.h"#include "G_Macro.h"TMirrorSurface::~TMirrorSurface(){	for(DWORD i = 0; i < Corners.size(); i++)      ReleasePT(Corners[i]);   Corners.erase(Corners.begin(), Corners.end());}TMirrorSurface::TMirrorSurface(TOpenGLWindow * pTargetWindow,				TVector3f pColor, float pTransparency, int pTexSize, float pHeight, std::vector<TVector3f*>pCorners){	//the target texture (TexSize) must be a power of 2	Corners = pCorners;   Height = pHeight;   Transparency = pTransparency;   Color = pColor;   TargetWindow = pTargetWindow;   TexSize = pTexSize;//NOTE: simply replace this with relevant code that will allocate a//TexSize*TexSize texture   ReflectionTxID = tc->Alloc(TexSize, TexSize)->Address;   ZeroMemory(&IdentityPlaneS, sizeof(IdentityPlaneS));   ZeroMemory(&IdentityPlaneT, sizeof(IdentityPlaneT));   ZeroMemory(&IdentityPlaneR, sizeof(IdentityPlaneR));   ZeroMemory(&IdentityPlaneQ, sizeof(IdentityPlaneQ));	IdentityPlaneS[0] = 1.f;	IdentityPlaneT[1] = 1.f;	IdentityPlaneR[2] = 1.f;	IdentityPlaneQ[3] = 1.f;}void TMirrorSurface::Create(){//NOTE: the same as calling glBindTexture()      RefTC->Bind(ReflectionTxID);		glEnable(GL_BLEND);   	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);		glColor4f(1.f, 1.f, 1.0f, 0.4f);      glMatrixMode(GL_MODELVIEW);	   glPushMatrix();   		glLoadIdentity();	   	glTexGenfv(GL_S, GL_EYE_PLANE, IdentityPlaneS);	   	glTexGenfv(GL_T, GL_EYE_PLANE, IdentityPlaneT);		   glTexGenfv(GL_R, GL_EYE_PLANE, IdentityPlaneR);   		glTexGenfv(GL_Q, GL_EYE_PLANE, IdentityPlaneQ);	   glPopMatrix();		glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);   	glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);	   glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);	   glTexGeni(GL_Q, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);   	glEnable(GL_TEXTURE_GEN_S);	   glEnable(GL_TEXTURE_GEN_T);   	glEnable(GL_TEXTURE_GEN_R);	   glEnable(GL_TEXTURE_GEN_Q);      glMatrixMode(GL_TEXTURE);      //set water (reflections) transcluency and color here      glColor4f(.8, .8, 1, .6);   	glPushMatrix();		   glLoadIdentity();		   glTranslatef(.5f, .5f, 0);		   glScalef(.5f, .5f, 1.f);			TargetWindow->RePlace();		   glMatrixMode(GL_MODELVIEW);			glBegin(GL_POLYGON);   			glVertex3f(Corners[0]->x, Height, Corners[0]->z);		   	glVertex3f(Corners[1]->x, Height, Corners[1]->z);   			glVertex3f(Corners[2]->x, Height, Corners[2]->z);		   	glVertex3f(Corners[3]->x, Height, Corners[3]->z);		   glEnd();		   glMatrixMode(GL_TEXTURE);		glPopMatrix();	   glMatrixMode(GL_MODELVIEW);	   glDisable(GL_TEXTURE_GEN_S);   	glDisable(GL_TEXTURE_GEN_T);	   glDisable(GL_TEXTURE_GEN_R);   	glDisable(GL_TEXTURE_GEN_Q);}


As I mentioned, this is ages old code and I didn''t bother to comment it too thoroughly for you. If there''s something you don''t understand, feel free to ask. Also note that TOpenGLWindow is just a wrapper class for a regular window utilising hardware acceleration through OpenGL and TOpenGLTextureContainer is just a wrapper class for managing textures. Hopefully you''ll understand what their function in all of this is.
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
Advertisement
Ahh, thank you very much!!!

Now to spend some time to digest your wonderful code! ^_^

Thank you!


-Jennifer
Hmm, my problem now is that I have a water surface that has ripples in them. As of now, the projected texture projects as though it is a flat texture. Meaning, when I render the water plane, you basically cannot see the ripples. I''ve read that I have to somehow get a virtual plane and the water surface plane and somehow intersect the two of them and pass it through the texture matrix.. or something along those lines. I didn''t quite understand it.

Do you know a way to basically change the texture coordinates so it somehow matches my water plane?

Once again, thank you very much!

-Jennifer
Well - this is out of my league since I''ve never done that. However, the simplest (but incorrect) way for you to create ripples would be to tessellate the water surface and model it according to some ripple generation technique (if you want to go for realism, fluid dynamics and the FFT approach is the thing to do, but as I said, I can''t help you with that).

The problem with rendering the mirrored surface to a texture using the stencil buffer is the one that the reflective image is literally flat and by mapping it on a wavy surface, you''ll get reflections where they''re not supposed to be. You''ll have to adopt a more powerful approach (cubemaps, perhaps) if you want the extra functionality.

Also note that stencil reflections only work with horizontal surfaces, which is yet another reason to go for something a little more dynamic.

I''m most certain that there''s a cubemap based approach to reflections available as a demo on nVidia''s developer page - perhaps you could start by looking there. Also, if I made any mistakes in my suggestions, I''d rather someone smarter (vincoof and _DarkWing_ pop to mind first) advise you and you should listem to them.

Hope this helps.
"Literally, it means that Bob is everything you can think of, but not dead; i.e., Bob is a purple-spotted, yellow-striped bumblebee/dragon/pterodactyl hybrid with a voracious addiction to Twix candy bars, but not dead."- kSquared
Crispy, tu ne peux pas t'empêcher de passer de la pommade à chaque fois que tu évoques le nom de Mirko ou le mien. Fais gaffe, je vais finir par croire que tu travailles chez l'Oreal ^^
< /french talk>

Ripples is beyond the purpose of the topic mentioned in the beginning of the thread.
Anyway, basically there are two ways of rendering ripples : per-vertex or per-pixel (you can combine both but it starts to be complicated).

For per-vertex ripples, you may use a vertex program to perturb the texture coordinate at the vertex level. For this to work you have to tesselate your water surface and create waves at each vertex.
For per-pixel ripples, you may use a fragment program to perturb the texture coordinate at the pixel level. It uses bump-mapping based techniques, and looks like EMBM (even if EMBM is not physically correct).
Either way, you will have to break the standard projective texturing somehow in order to take into account the slight image distortion needed by ripple rendering, which means that you will step into shaders. This road may be very difficult, but I envy you if you can handle it.
You may take a look at nVidia and ATi developer sites where you will find many useful resource about reflections, bump mapping, and vertex and fragment programs. Generally these sites will lead you to cubemap reflections as they tend to be much more flexible, but be careful as they also tend to be much slower and much more complex.

Also, please note that two general reflection methods exist : stencil reflections and texture reflections, each one having its own pro's and con's. This time we're talking about texture reflections, and it's the right choice for ripples. Stencil reflections can not achieve this effect (though stencils have other advantages of course). So don't read papers about stencil reflections, it's a dead end for this effect.

[edited by - vincoof on May 17, 2004 7:18:22 AM]

This topic is closed to new replies.

Advertisement