Sign in to follow this  
yogr

Calculating projective texture coordinates

Recommended Posts

Hi guys, I'm practicing with projective texture mapping for the very first time and I'm having some troubles calculating the texture coords. I'm trying to implement it using the fixed pipeline (without setting the texture transform matrix), then I will try using the texture transform matrix and finally using a vertex shader. I have have simple scene with a rotating cube on a reflecting plane: the cube is a D3DXMesh, while the plane is made up of 4 vertices in an indexed vertex buffer. I reflect the camera below the plane surface and render the scene to a texture, then I lock the vertex buffer and i loops through the vertices to assign a texture coord. I've read a lot of articles, but I still have some doubts: in the "reflective water rendering" article I've learned that the transform matrix is obtained by: remapMatrix * matProj * reflectedMatView * matWorld, then the resulting tex coords are (r,s,t,q) => (r/q, s/q, t/q, 1). I can't understand why the remap matrix is applied before the division by q... when I transform a position vector using the view and projection matrix I obtain coordinates in homogeneus clip space, then dividing by w i get the values ranging from -1 to 1 and THEN I should remap the values from -1,1 to 0,1... is It wrong? Here's my code... thanks!
struct Vertex {
	float x, y, z;
	float nx, ny, nz;
	DWORD color;
	float u0, v0;
	float u1, v1;
};
const DWORD FVF_VERTEX = D3DFVF_XYZ | D3DFVF_NORMAL | D3DFVF_DIFFUSE | D3DFVF_TEX1 | D3DFVF_TEX2;

Vertex data[]={
	{-100.0, -10.0, 100.0, 0.0, 1.0, 0.0, 0xFF000000, 0.0, 5.0, 0.0, 1.0},    
	{100.0, -10.0, -100.0, 0.0, 1.0, 0.0, 0xFF000000, 5.0, 0.0, 1.0, 0.0},  
	{-100.0, -10.0, -100.0, 0.0, 1.0, 0.0, 0xFF000000, 0.0, 0.0, 0.0, 0.0}, 
	{100.0, -10.0, 100.0, 0.0, 1.0, 0.0, 0xFF000000, 5.0, 5.0, 1.0, 1.0}, 
};

D3DXMATRIX matRemap(0.5, 0,   0,   0.5,
					0,   0.5, 0,   0.5,
					0,   0,   0.5, 0.5,
					0,   0,   0,   1.0);

void renderScene() {
	// Clear the render target and the zbuffer 
    pDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB( 255, 70, 70, 70 ), 1.0f, 0 );
	
	pDevice->SetTexture(0, tex);
	
	D3DXMATRIX id;
	pDevice->SetTransform(D3DTS_WORLD, D3DXMatrixIdentity(&id));
	pDevice->SetStreamSource(0, vb, 0, sizeof(Vertex));
	pDevice->SetIndices(ib);
	pDevice->SetFVF(FVF_VERTEX);
	pDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 4, 0, 2);

	// Draw the box
	pDevice->SetTexture(0, 0);
	pDevice->SetTexture(1, 0);
	D3DXMATRIX rot;
	D3DXMatrixRotationYawPitchRoll(&rot, yaw, pitch, roll);
	rot._42 = 5;
	pDevice->SetTransform(D3DTS_WORLD, &rot);
	pBox->DrawSubset(0);
}

void renderReflection() {
	D3DXVECTOR3 wRefEye = wEyePos;
	wRefEye.y = - 10 - (wEyePos.y + 10);
	D3DXMATRIX refMat;
//refMat is the reflected view matrix
	pDevice->SetTransform(D3DTS_VIEW, D3DXMatrixLookAtLH(&refMat, &wRefEye, &wLookAt, &wUp));
	pDevice->SetTransform(D3DTS_PROJECTION, &matRTTProj);
	pDevice->SetRenderTarget(0, rttSurface);

	if ( SUCCEEDED( pDevice->BeginScene() ) )
    {
		pDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_ARGB(255, 70, 70, 70), 1.0f, 0);
		pDevice->SetTexture(1, NULL);
		renderScene();
		pDevice->EndScene();
	}

	//D3DXMATRIX matProjTex;
	D3DXMATRIX matProjTex = matRemap * matProj * refMat;
	
	// Project the texture
	Vertex *vertices = NULL;
	vb->Lock(0, 0, (VOID **) &vertices, D3DLOCK_DISCARD);
	int len = sizeof(vertices);
	for (int i=0; i<len; i++) {
		D3DXVECTOR4 c(vertices[i].x, vertices[i].y, vertices[i].z, 1.0);
		D3DXVECTOR4 p;
		D3DXVec4Transform(&p, &c, &matProjTex);
		p /= p.w;
		vertices[i].u1 = p.x;
		vertices[i].v1 = p.y;
	}
	vb->Unlock();

// Reset the view and proj matrices
	pDevice->SetTransform(D3DTS_VIEW, &matView);
	pDevice->SetTransform(D3DTS_PROJECTION, &matProj);
	pDevice->SetRenderTarget(0, pBackBuffer);
}

//--------------------------------------------------------------------------------------
// Render the scene using the D3D9 device
//--------------------------------------------------------------------------------------
void CALLBACK OnD3D9FrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
{
    HRESULT hr;

    renderReflection();
	
	pDevice->SetTexture(1, 0);

    // Render the scene
    if ( SUCCEEDED( pd3dDevice->BeginScene() ) )
    {
		pDevice->SetTexture(1, rttTex);
		renderScene();
		
		V( pd3dDevice->EndScene() );
    }

	dLastTime = curTime;
}


Share this post


Link to post
Share on other sites
I'm having some results using this method, but it's still wrong!

WRONG!


D3DXMATRIX matProjTex;
D3DXMATRIX matProjTex = reflectedViewMat * matProj;

// Project the texture
Vertex *vertices = NULL;
vb->Lock(0, 0, (VOID **) &vertices, D3DLOCK_DISCARD);
int len = sizeof(vertices);
for (int i=0; i<len; i++) {
// Vertex Position
D3DXVECTOR4 c(vertices[i].x, vertices[i].y, vertices[i].z, 1.0);
D3DXVECTOR4 p;
D3DXVec4Transform(&p, &c, &matProjTex);
p /= p.w;
// Bias (this is the remapMatrix)
vertices[i].u1 = p.x * 0.5 + 0.5;
vertices[i].v1 = p.y * 0.5 + 0.5;
}
vb->Unlock();


Share this post


Link to post
Share on other sites

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