Skip to main content
gamedev.net
🔒 Locked

Quad coverage for render to target (Solved)

Started by DrGUI 9 replies 1.2k views
Original Post
DrGUI
DrGUI
Hi there! I know what to do after I can get one render target just copied to another. But how do you set this up? I already know that you need to move the quad up and left by 0.5 to align the texel centres for when DX converts the floating point texture coordinates into integers. But if you're shifting it left and up, won't you be left with little gaps at the bottom and right? Probably not :( This is what I have already: //Bottom left verts[0].X = m_Rectangle.Left - 0.5; verts[0].Y = m_Rectangle.Bottom - 0.5; verts[0].Z = z; verts[0].Rhw = 1; verts[0].Tu = halfTexelWidth; verts[0].Tv = 1 - halfTexelHeight; //Top left verts[1].X = m_Rectangle.Left - 0.5; verts[1].Y = m_Rectangle.Top - 0.5; verts[1].Z = z; verts[1].Rhw = 1; verts[1].Tu = halfTexelWidth; verts[1].Tv = halfTexelHeight; //Bottom right verts[2].X = m_Rectangle.Right - 0.5; verts[2].Y = m_Rectangle.Bottom - 0.5; verts[2].Z = z; verts[2].Rhw = 1; verts[2].Tu = 1 - halfTexelWidth; verts[2].Tv = 1 - halfTexelHeight; //Top right verts[3].X = m_Rectangle.Right - 0.5; verts[3].Y = m_Rectangle.Top - 0.5; verts[3].Z = z; verts[3].Rhw = 1; verts[3].Tu = 1 - halfTexelWidth; verts[3].Tv = halfTexelHeight; Is that right? Thanks [Edited by - DrGUI on July 21, 2005 4:34:27 AM]
mdias
mdias
If you just want to copy the texture contents to another texture use the IDirect3DDevice9::StretchRect method.
As for the texture alignment issue, I don't know how to help you.
DrGUI
DrGUI
Thanks for replying!
Yes, that would be the best way if I just wanted to copy a texture, but you're right, I'm trying to do render-to-texture, and to do that I need the correct alignment.

Perhaps I should have made it clearer that I'm doing it this way to convolve the texture using a pixel shader rather than just copying.
DrGUI
DrGUI
The OGL code for rendering a quad for a render target was:

glBegin(GL_QUADS);
glTexCoord2f(0.0f, 0.0f); glVertex3f( 0.0f, 0.0f, 0.0f);
glTexCoord2f(nWidth, 0.0f); glVertex3f(nWidth, 0.0f, 0.0f);
glTexCoord2f(nWidth, nHeight); glVertex3f(nWidth, nHeight, 0.0f);
glTexCoord2f(0.0f, nHeight); glVertex3f( 0.0f, nHeight, 0.0f);
glEnd();

So do you think I should take out the halfTexelWidth/Height offsets and do it like above, just offset by 0.5?
Drakex
Drakex
DrGUI - yep. All you need to do is adjust the position by -0.5, -0.5, and leave the UV coords alone. I do this for my custom sprite engine, and the pixels match up perfectly.
___________Hoo-rah.
DrGUI
DrGUI
Quote:

I guess I should ask you this now before we go any further - are you drawing the sprites yourself, or are you using Direct3D.Sprite? And are you pretransforming your sprites? I'm not sure why you you're calculating and concatenating the projection matrix for every rectangle.

Also - take out the texelWidth/Height stuff. You don't need it if you use the projection matrix I sent you last message. As long as it's offset by 0.5, you don't need to change the rectangle.

Thanks for the replies firstly...

I am drawing the rectangle myself, not using Direct3D.Sprite. I used to pretransform my rectangles but I want to reuse the geometry and make it more flexible. I now have a quad with vertices from -1 to 1 in the xy plane.

Yes, I found my error shortly after reading your reply - the rectangles were always filling the screen because I was creating the projection with the texture width. Now I use the viewport width instead so I can create the projection matrix only once per resize.

Sorry about the texelWidth/height stuff - that was something different and I'm not using it yet.


Right - this is what I have now and it seems to be working. I had to change the parameters to OrthoLH but we probably just have different geometry. Apparantly a good test for texel sampling is the Game of Life implemented in a pixel shader - I'll have to do that once I've finished my image processing framework. Or I could just render to target lots to see if the result gets blurred or offset :S

The two solutions (I'll go with the one with the offsets in the projection matrix if it works - hide away the details [smile])
public static Matrix GetRectangleMatrix(System.Drawing.RectangleF rectangle){//	Matrix projection = Matrix.OrthoLH(m_Viewport.Width, m_Viewport.Height, 0, 100);//	Matrix scaling = Matrix.Scaling(rectangle.Width / 2f, rectangle.Height / 2f, 1);//	Matrix translation = Matrix.Translation(rectangle.X - 0.5f, rectangle.Y + 0.5f, 0);//	return (scaling * translation) * projection; //don't know if bracket needed but just making sure	float halfVPWidth = m_Viewport.Width / 2f;	float halfVPHeight = m_Viewport.Height / 2f;	Matrix projection = Matrix.OrthoOffCenterLH(-halfVPWidth  + 0.5f, halfVPWidth  + 0.5f,			                                    -halfVPHeight - 0.5f, halfVPHeight - 0.5f, 0, 100);	Matrix scaling = Matrix.Scaling(rectangle.Width / 2f, rectangle.Height / 2f, 1);	Matrix translation = Matrix.Translation(rectangle.X, rectangle.Y, 0);	return (scaling * translation) * projection; //don't know if bracket needed but just making sure}


By the way, I had to invert the y offsets because it seems from my experimentation with the offsets that positive y is up the screen.

Thanks, I'll put this in the thread too in case anyone's interested - I'm sure he wouldn't mind :P
Drakex
Drakex
Quote:
By the way, I had to invert the y offsets because it seems from my experimentation with the offsets that positive y is up the screen.


Oh yeah, I forgot about that. I have my sprite engine set up so it's like true 2D graphics - top-left of the screen is (0,0) and coords increase down and to the right. :)

Though something that might help with performance - calculate the projection matrix once before rendering all your sprites. It never changes per-sprite, so there's no need to calculate it per-sprite.

Glad I could help!
___________Hoo-rah.
DrGUI
DrGUI
Quote:

Oh yeah, I forgot about that. I have my sprite engine set up so it's like true 2D graphics - top-left of the screen is (0,0) and coords increase down and to the right. :)

That's what I'm trying to get!
I finally got it with this code, but it's a bit of a hack as I add the viewport height on again in the translation:
public static Matrix GetRectangleMatrix(System.Drawing.RectangleF rectangle){	Matrix projection = Matrix.OrthoOffCenterLH(0.5f, m_Viewport.Width + 0.5f,			                                    -0.5f, m_Viewport.Height - 0.5f, 0, 100);	Matrix geoTranslation = Matrix.Translation(1, -1, 0);	Matrix scaling = Matrix.Scaling(rectangle.Width / 2f, rectangle.Height / 2f, 1);	Matrix translation = Matrix.Translation(rectangle.X, rectangle.Y + m_Viewport.Height, 0);	return (geoTranslation * scaling * translation) * projection; //don't know if bracket needed but just making sure}

How did you invert the y axis? I tried swapping the top and bottom parameters of the projection but everything just disappeared :( What geometry did you use? I think I'll try changing mine to 0 to 1 rather than -1 to 1 to see if that makes the calculations easier.

Quote:

Though something that might help with performance - calculate the projection matrix once before rendering all your sprites. It never changes per-sprite, so there's no need to calculate it per-sprite.

Thanks; I already do that but I just wanted the matrix handy so I could fiddle parameters. Nothing moves because my quads are the background image, presentation quad for glow, quad for render-to-target to convolve glow and one to show the contents of the render targets [smile] So their updates all stem from OnResetDevice anyways.

Thanks again!
Drakex
Drakex
Quote:
I tried swapping the top and bottom parameters of the projection but everything just disappeared


Try turning off backface culling. I think I ran into the same problem, and that fixed it.
___________Hoo-rah.
DrGUI
DrGUI
It works!! Thank you!! [smile][grin][smile]

I found out in the process that setting the cullmode in an effect file does not seem to work. I managed to reorder my quad's vertices though to make it work :) (difficult as I wasn't using a index buffer to 4 verts)

Here's the code for anyone who wants to know:
public static Matrix GetRectangleMatrix(Direct3D.Viewport viewport, System.Drawing.RectangleF rectangle){ //Precalculate projection matrix	//Geometry winds clockwise to not be culled	Matrix projection = Matrix.OrthoOffCenterLH(0.5f, viewport.Width + 0.5f, viewport.Height + 0.5f, 0.5f, 0, 100);	Matrix scaling = Matrix.Scaling(rectangle.Width, rectangle.Height, 1);	Matrix translation = Matrix.Translation(rectangle.X, rectangle.Y, 0);	return (scaling * translation) * projection;}//Snippet for vertex buffer//Create the vertex bufferconst float xmin = 0;const float xmax = 1;const float ymin = 0;const float ymax = 1;const float z = 1.0f;//Create vertex buffer if requiredif (m_VB == null){	//Create the buffer //TODO - WriteOnly	m_VB = new Direct3D.VertexBuffer(typeof(Direct3D.CustomVertex.PositionTextured), 4, m_Device, 0, Direct3D.CustomVertex.PositionTextured.Format, Direct3D.Pool.Managed);	//Fill the vertex buffer	Direct3D.CustomVertex.PositionTextured[] verts = m_VB.Lock(0, Direct3D.LockFlags.None) as Direct3D.CustomVertex.PositionTextured[];	//Top left	verts[0].X = xmin;	verts[0].Y = ymin;	verts[0].Z = z;	verts[0].Tu = 0;	verts[0].Tv = 0;	//Top right	verts[1].X = xmax;	verts[1].Y = ymin;	verts[1].Z = z;	verts[1].Tu = 1;	verts[1].Tv = 0;	//Bottom left	verts[2].X = xmin;	verts[2].Y = ymax;	verts[2].Z = z;	verts[2].Tu = 0;	verts[2].Tv = 1;	//Bottom right	verts[3].X = xmax;	verts[3].Y = ymax;	verts[3].Z = z;	verts[3].Tu = 1;	verts[3].Tv = 1;	m_VB.Unlock();}
Drakex
Drakex
w00tage!
___________Hoo-rah.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.