Click here to Skip to main content
15,887,746 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
We have a problem with creation of transparent vertex points as little as pixels in Direct3D9.
There is a square vertex with a map (a bmp file) as its texture. We need to show some transparent point vertexes over it. Unfortunately, instead of that portion of square texture that is behind of the points all of square texture was displayed as point’s texture.
What is the problem?
Thank you in advance for your hints.
Posted

The approach I would take to this is to make a 2 dimensional array of vertices (as if you were going to render a landscape) and set the render mode to Point.
Initialise the points in the array to have the correct XYZ position (and RGB or RGBA colour if you want different colours/alpha).

Transparency is possible, just be sure to draw the vertices last, so they can pick up the colour of the pixels below them.

This can give some nice effects without the need for writing shaders (if you don't know how).

Depending on what you are storing in the bitmap you could use that to initialise the colour of the vertices before loading them onto the graphics card as a model.

C++
#define D3DFVF_MYVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE) //This is used to tell the Direct3D fixed function pipeline what data is in our custom virtex

typedef struct {
	float x, y, z;
	DWORD col; //optional
} MyVertex;

MyVertex *BuildArray() {
	//Bitmap files are very easy to read if you need to
	//This makes points between -w to w-2 and -h to h-2, spaced 2 units apart at z=0
	int w = 100;
	int h = 50;
	MyVertex arr = (MyVertex)malloc(w * h * sizeof(MyVertex));
	MyVertex p = arr; //This is used as an optimisation, to save computing the offset all the time
	for (int y = 0; y < h; ++y){
		for (int x = 0; x < w; ++x) {
			p->x = x * 2.0f - w;
			p->y = y * 2.0f - h;
			p->z = 0.0f;
			p->col = 0xFFFFFFFF; //This is a non-transparent white
			++p;
		}
	}
}
 
Share this answer
 
Comments
zoltrix61 31-Oct-11 2:40am    
Thank you for your response but I can not exactly comprehend your means.
In my codes that have been copied under these lines, I first combine two images with using of Alpha Blending Technique, and then 12 points in various sizes are drawn over the combined images. I want to draw these points transparently. How it is possible?
Any help is appreciated.
Bests



#define D3DFVF_CUSTOMVERTEX (D3DFVF_DIFFUSE | D3DFVF_XYZ | D3DFVF_TEX2 )

//structures
struct D3DVERTEX
{
float fX,
fY,
fZ;
DWORD color;
float fU1,
fV1;
float fU2,
fV2;

};

#define D3DFVF_CUSTOMVERTEX2 (D3DFVF_XYZ | D3DFVF_PSIZE | D3DFVF_DIFFUSE)

//structures
struct D3DVERTEX2
{
float fX,
fY,
fZ,
fSize;
DWORD dwColor;
};

D3DVERTEX aQuad[] =
{
{-1.0f, 1.0f, 2.5f, D3DCOLOR_ARGB(255,255,255,255), 0.0f,0.0f,0.0f,0.0f},
{-1.0f, -1.0f, 2.5f, D3DCOLOR_ARGB(255,255,255,255), 0.0f,1.0f,0.0f,1.0f
{1.0f, 1.0f, 2.5f, D3DCOLOR_ARGB(255,255,255,255), 1.0f,0.0f,1.0f,0.0f
{1.0f, -1.0f, 2.5f, D3DCOLOR_ARGB(255,255,255,255), 1.0f,1.0f,1.0f,1.0f}
};



D3DVERTEX2 aPoints[] =
{
{-0.5f,0.005f,1.5f, 10.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.055f,1.5f, 20.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.55f,1.5f, 20.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.45f,1.5f, 20.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.40f,1.5f, 20.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.35f,1.5f, 10.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.30f,1.5f, 20.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.25f,1.5f, 20.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.20f,1.5f, 5.0f, D3DCOLOR_ARGB(220,255,0,0)},
{-0.5f,0.15f,1.5f, 20.0f, D3DCOLOR_ARGB(100,128,128,128)},
{-0.5f,0.10f,1.5f, 20.0f, D3DCOLOR_ARGB(255,128,128,128)},
{-0.5f,0.50f,1.5f, 5.0f, D3DCOLOR_ARGB(220,0,0,0)}
};



g_App.GetDevice()->CreateVertexBuffer(sizeof(aQuad),D3DUSAGE_WRITEONLY,D3DFVF_CUSTOMVERTEX,D3DPOOL_MANAGED,&pQuadVB,NULL);

g_App.GetDevice()->CreateVertexBuffer(sizeof(aPoints),D3DUSAGE_POINTS | D3DUSAGE_WRITEONLY,D3DFVF_CUSTOMVERTEX2,D3DPOOL_MANAGED,&pPointsVB,NULL);


pPointsVB->Lock(0,sizeof(aPoints),&pData,0);
memcpy(pData,aPoints,sizeof(aPoints));
pPointsVB->Unlock();


pQuadVB->Lock(0,sizeof(aQuad),(void**)&pData,0);
memcpy(pData,aQuad,sizeof(aQuad));
pQuadVB->Unlock();

D3DXCreateTextureFromFileA(g_App.GetDevice(),"Text1.bmp",&pMap1);
D3DXCreateTextureFromFileA(g_App.GetDevice(),"Text2.bmp",&pMap2);


////////////////////////////////////////////////////////////////////
void CApplication::InitScene(void)
{
D3DXMatrixPerspectiveFovLH(&m_matProjection,m_fFieldOfView,m_fAspectRatio,m_fNearPlane,m_fFarPlane);
m_pDirect3DDevice->SetTransform(D3DTS_PROJECTION,&m_matProjection);

m_pDirect3DDevice->SetRenderState(D3DRS_AMBIENT,RGB(255,255,255));
m_pDirect3DDevice->SetRenderState(D3DRS_LIGHTING,false);
m_pDirect3DDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
m_pDirect3DDevice->SetRenderState(D3DRS_ZENABLE,D3DZB_FALSE);


for(unsigned i = 0;i < 8;++i)
{
m_pDirect3DDevice->SetSamplerState(i,D3DSAMP_MINFILTER,D3DTEXF_LINEAR);
m_pDirect3DDevice->SetSamplerState(i,D3DSAMP_MAGFILTER,D3DTEXF_LINEAR);
m_pDirect3DDevice->SetSamplerState(i,D3DSAMP_MIPFILTER,D3DTEXF_ANISOTROPIC);
m_pDirect3DDevice->SetSamplerState(i,D3DSAMP_MAXANISOTROPY,m_dwAnisotropy);
}


m_pDirect3DDevice->SetTextureStageState(0,D3DTSS_ALPHAARG1,D3DTA_DIFFUSE);
m_pDirect3DDevice->SetTextureStageState(0,D3DTSS_ALPHAOP,D3DTOP_SELECTARG1);

m_pDirect3DDevice->SetTextureStageState(1,D3DTSS_TEXCOORDINDEX,1);
m_pDirect3DDevice->SetTextureStageState(1,D3DTSS_COLORARG1,D3DTA_TEXTURE);
m_pDirect3DDevice->SetTextureStageState(1,D3DTSS_COLORARG2,D3DTA_CURRENT);
m_pDirect3DDevice->SetTextureStageState(1,D3DTSS_COLOROP,D3DTOP_MODULATE);
m_pDirect3DDevice->SetTextureStageState(1,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
m_pDirect3DDevice->SetTextureStageState(1,D3DTSS_ALPHAARG2,D3DTA_CURRENT);
m_pDirect3DDevice->SetTextureStageState(1,D3DTSS_ALPHAOP,D3DTOP_MODULATE);


m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_TEXCOORD
zoltrix61 31-Oct-11 2:44am    
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_TEXCOORDINDEX,2);
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_COLORARG1,D3DTA_TEXTURE);
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_COLORARG2,D3DTA_CURRENT);
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_COLOROP,D3DTOP_MODULATE);
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_COLORARG1,D3DTA_CURRENT);
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_COLOROP,D3DTOP_SELECTARG1);
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_ALPHAARG1,D3DTA_TEXTURE);
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_ALPHAARG2,D3DTA_CURRENT);
m_pDirect3DDevice->SetTextureStageState(2,D3DTSS_ALPHAOP,D3DTOP_MODULATE);

}//InitScene


////////////////////////////////////////////

if(g_App.CheckDevice())
{
g_App.GetDevice()->Clear(0,NULL,D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,D3DCOLOR_XRGB(128,128,128),1.0f,0);
g_App.GetDevice()->BeginScene();

g_App.GetDevice()->SetTexture(0,pMap1);
g_App.GetDevice()->SetTexture(1,pMap2);


g_App.GetDevice()->SetFVF(D3DFVF_CUSTOMVERTEX);
g_App.GetDevice()->SetStreamSource(0,pQuadVB,0,sizeof(D3DVERTEX));
g_App.GetDevice()->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2);

g_App.GetDevice()->SetFVF(D3DFVF_CUSTOMVERTEX2);
g_App.GetDevice()->SetStreamSource(0,pPointsVB,0,sizeof(D3DVERTEX2));
g_App.GetDevice()->DrawPrimitive(D3DPT_POINTLIST,0,12);



g_App.GetDevice()->EndScene();
g_App.GetDevice()->Present(NULL,NULL,NULL,NULL);
}
Andrew Brock 31-Oct-11 8:53am    
To get alpha blending working you need to:
a. Set up the backbuffer with a format of D3DFMT_X8R8G8B8. The backbuffer does not support D3DFMT_A8R8G8B8 because this is what is drawn to screen, and you cannot draw alpha.
D3DPRESENT_PARAMETERS d3dpp; //This is your initialisation parameters
d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;

b. Now we need to enable alpha blending, and select the mode.
LPDIRECT3DDEVICE9 g_pd3dDevice; //This is your device
g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

If you need, I can post code which will do (what I think) you are after. Have a go for yourself first tho.
zoltrix61 1-Nov-11 3:40am    
I appreciate that you helped me.
With adding 3 line code:

g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);

the points got transparent,but the problem is that the color of Quad vertices(here is for example white) affect on transparency and reduce the quality of picture,as you feel you are looking to picture through a white
cover.


having your sample code would help me so much.
Ok, this code will run with just the main.cpp file, but will work best with a texture demo.bmp, and the shader file Shader.fx

You will need to grab or make a bitmap image and place it in the working directory, and name it demo.bmp. This will texture the quad.
The shader file should also be placed in the working directory.

Note that this code does not use the Z buffer. This means when you draw something, it will always draw on top of whatever is there, even if it should be at the back. This avoids tearing since everything is rendered at z=0.

The shader allows for advanced effects, I used it to render a perfect circle at any resolution, but they allow for almost limitless special effects.

If you want to texture the points, you can set the texture, there is already a g_pd3dDevice->SetTexture(0, NULL);, just create a texture and shove it in there. It will need an alpha channel to work however, so use a PNG or something.

The single pixel points are there, but they may be a bit hard to see, depending on the texture. They are also rendered with transparency.

I have provided some commenting, but you seem to have a reasonable handle on the basics of DirectX, so I didn't do to many.
If you need further explanation of any of the code, just post which parts you are having trouble with.

Just shove this code into a new Win32 GUI project and go. There are no special settings.

Main.cpp:
C++
#include <Windows.h>
#include <tchar.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <mmsystem.h> //for timeGetTime to rotate it around
#include <stdio.h>

#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "winmm.lib")

typedef struct {
	D3DXVECTOR3 vPos;
    D3DCOLOR colDiffuse;
	D3DXVECTOR2 vUV;
} PicVertex;

typedef struct {
	D3DXVECTOR3 vPos;
    D3DCOLOR colDiffuse;
	D3DXVECTOR2 vUV;
} PointVertex;

typedef struct {
	D3DXVECTOR3 vPos;
    D3DCOLOR colDiffuse;
} PixelVertex;

#define D3DFVF_PICVERTEX (D3DFVF_DIFFUSE | D3DFVF_XYZ | D3DFVF_TEX1)
#define D3DFVF_PIXELVERTEX (D3DFVF_DIFFUSE | D3DFVF_XYZ)
#define D3DFVF_POINTVERTEX (D3DFVF_DIFFUSE | D3DFVF_XYZ | D3DFVF_TEX1)

#define ADD_POINT_UV(x, y, z, size, col, u, v) { D3DXVECTOR3(x + (u - 0.5f) * size, y + (v - 0.5f) * size, z), col, D3DXVECTOR2(u, v) }
#define ADD_POINT(x, y, z, size, col) \
	ADD_POINT_UV(x, y, z, size, col, 0.0f, 1.0f),\
	ADD_POINT_UV(x, y, z, size, col, 0.0f, 0.0f),\
	ADD_POINT_UV(x, y, z, size, col, 1.0f, 1.0f),\
	ADD_POINT_UV(x, y, z, size, col, 1.0f, 1.0f),\
	ADD_POINT_UV(x, y, z, size, col, 0.0f, 0.0f),\
	ADD_POINT_UV(x, y, z, size, col, 1.0f, 0.0f),
#define ADD_PIXEL(x, y, z, col) { D3DXVECTOR3(x, y, z), col },

LPDIRECT3D9 g_pD3D = NULL; //Our DirectX handle
LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; //Our DirectX device
LPDIRECT3DVERTEXBUFFER9 g_pQuadVB = NULL; //The vertex buffer for the quad 4 verts per quad
LPDIRECT3DVERTEXBUFFER9 g_pPixelVB = NULL; //The vertex buffer for the single pixel points, 1 vert per pixel
LPDIRECT3DVERTEXBUFFER9 g_pPointVB = NULL; //The vertex buffer for our multi-pixel points, 4 verts per quad
LPD3DXEFFECT g_pEffect = NULL; //The shader file
D3DXHANDLE g_pPointEffect = NULL; //The effect for rendering the point
D3DXHANDLE g_pFFEffect = NULL; //The effect for rendering everything else (this is a NULL effect, which is the default Fixed Function pipeline in DX9)
LPDIRECT3DVERTEXDECLARATION9 g_pVertexDeclaration = NULL; //The input data specification for our custom shader
LPDIRECT3DTEXTURE9 g_pTexture = NULL; //The texture to be rendered onto the quad

//The quad, same as yours
PicVertex aQuad[] =  {
	//The quad that you will texture. I have not textured it, but I'm sure you can figure that out
	{ D3DXVECTOR3(-1.0f,  1.0f, 0.0f), D3DCOLOR_ARGB(255, 255, 255, 255), D3DXVECTOR2(0.0f, 0.0f) },
	{ D3DXVECTOR3(-1.0f, -1.0f, 0.0f), D3DCOLOR_ARGB(255, 255, 255, 255), D3DXVECTOR2(0.0f, 1.0f) },
	{ D3DXVECTOR3( 1.0f,  1.0f, 0.0f), D3DCOLOR_ARGB(255, 255, 255, 255), D3DXVECTOR2(1.0f, 0.0f) },
	{ D3DXVECTOR3( 1.0f, -1.0f, 0.0f), D3DCOLOR_ARGB(255, 255, 255, 255), D3DXVECTOR2(1.0f, 1.0f) }
};

//The points and pixels to draw. These are not quite the same as your points.
//I have turned down the alpha value to make the effect more noticable
PointVertex g_colPoints[] = {
	//All non-pixel sized points in here
	ADD_POINT(-0.5f, 0.005f, 0.0f, 0.05f,  D3DCOLOR_ARGB(180, 255, 0,   0)  )
	ADD_POINT(-0.5f, 0.055f, 0.0f, 0.05f,  D3DCOLOR_ARGB(180, 255, 0,   0)  )
	ADD_POINT(-0.5f,  0.55f, 0.0f, 0.05f,  D3DCOLOR_ARGB(180, 255, 0,   0)  )
	ADD_POINT(-0.5f,  0.45f, 0.0f, 0.05f,  D3DCOLOR_ARGB(180, 255, 0,   0)  )
	ADD_POINT(-0.5f,  0.40f, 0.0f, 0.025f, D3DCOLOR_ARGB(180, 255, 0,   0)  )
	ADD_POINT(-0.5f,  0.35f, 0.0f, 0.05f,  D3DCOLOR_ARGB(180, 255, 0,   0)  )
	ADD_POINT(-0.5f,  0.30f, 0.0f, 0.05f,  D3DCOLOR_ARGB(180, 255, 0,   0)  )
	ADD_POINT(-0.5f,  0.25f, 0.0f, 0.012f, D3DCOLOR_ARGB(180, 255, 0,   0)  )
	ADD_POINT(-0.5f,  0.20f, 0.0f, 0.05f,  D3DCOLOR_ARGB(100, 128, 128, 128))
	ADD_POINT(-0.5f,  0.15f, 0.0f, 0.05f,  D3DCOLOR_ARGB(255, 128, 128, 128))
	ADD_POINT(-0.1f,  0.10f, 0.0f, 0.50f,  D3DCOLOR_ARGB(180, 0,   0,   0)  )
};

PixelVertex g_colPixels[] = {
	//All the single pixel points in here
	ADD_PIXEL(0.5f, 0.005f, 0.0f, D3DCOLOR_ARGB(220, 255, 0,   0)  )
	ADD_PIXEL(0.5f, 0.055f, 0.0f, D3DCOLOR_ARGB(220, 255, 0,   0)  )
	ADD_PIXEL(0.5f,  0.55f, 0.0f, D3DCOLOR_ARGB(220, 255, 0,   0)  )
	ADD_PIXEL(0.5f,  0.45f, 0.0f, D3DCOLOR_ARGB(220, 255, 0,   0)  )
	ADD_PIXEL(0.5f,  0.40f, 0.0f, D3DCOLOR_ARGB(220, 255, 0,   0)  )
	ADD_PIXEL(0.5f,  0.35f, 0.0f, D3DCOLOR_ARGB(220, 255, 0,   0)  )
	ADD_PIXEL(0.5f,  0.30f, 0.0f, D3DCOLOR_ARGB(220, 255, 0,   0)  )
	ADD_PIXEL(0.5f,  0.25f, 0.0f, D3DCOLOR_ARGB(220, 255, 0,   0)  )
	ADD_PIXEL(0.5f,  0.20f, 0.0f, D3DCOLOR_ARGB(100, 128, 128, 128))
	ADD_PIXEL(0.5f,  0.15f, 0.0f, D3DCOLOR_ARGB(255, 128, 128, 128))
	ADD_PIXEL(0.5f,  0.10f, 0.0f, D3DCOLOR_ARGB(220, 0,   0,   0)  )
};

bool InitD3D(HWND hWnd) {
	//Create the device, not much here
	if ((g_pD3D = Direct3DCreate9(D3D_SDK_VERSION)) == NULL) {
		return false;
	}
	D3DPRESENT_PARAMETERS d3dpp;
	ZeroMemory(&d3dpp, sizeof(d3dpp));
	d3dpp.Windowed = TRUE;
	d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
	d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
	d3dpp.EnableAutoDepthStencil = TRUE;
	d3dpp.AutoDepthStencilFormat = D3DFMT_D16;
	if (FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice))) {
		return false;
	}
	g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // Allows faces to be visible on both sides
	g_pd3dDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
	g_pd3dDevice->SetRenderState(D3DRS_ZENABLE, FALSE); //We don't need the Z buffer. This allows us to render the pixels with the same Z as the quad and not have them artifact
	//The 3 lines to set up alpha blending
	g_pd3dDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
	g_pd3dDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
	g_pd3dDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
	//Compile and set up our shader. You can find more information on shaders by googling "Directx 9 shader"
	LPD3DXBUFFER pErrors;
	if (FAILED(D3DXCreateEffectFromFile(g_pd3dDevice, _T("Shader.fx"), NULL, NULL, 0, NULL, &g_pEffect, &pErrors))) {
		if (pErrors == NULL) {
			MessageBox(HWND_DESKTOP, _T("Shader.fx not found"), _T("Shader missing"), MB_OK | MB_ICONERROR);
		} else {
			MessageBoxA(HWND_DESKTOP, (LPSTR)pErrors->GetBufferPointer(), "Shader compile error", MB_OK | MB_ICONERROR);
			pErrors->Release();
		}
		//return false;
	} else {
		g_pPointEffect = g_pEffect->GetTechniqueByName("Point");
		g_pFFEffect = g_pEffect->GetTechniqueByName("FixedFunction");
		//The input data that we send to our custom shader. This is similar to the FVFs that are #defined above
		D3DVERTEXELEMENT9 decl[] = {
			{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
			{ 0, 12, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
			{ 0, 16, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
			D3DDECL_END()
		};
		g_pd3dDevice->CreateVertexDeclaration(decl, &g_pVertexDeclaration);
	}
	return true;
}

void Cleanup() {
	//Nothing special here, just release everything
	if (g_pEffect != NULL) {
		g_pEffect->Release();
	}
	if (g_pQuadVB != NULL) {
		g_pQuadVB->Release();
	}
	if (g_pPixelVB != NULL) {
		g_pPixelVB->Release();
	}
	if (g_pPointVB != NULL) {
		g_pPointVB->Release();
	}
	if (g_pVertexDeclaration != NULL) {
		g_pVertexDeclaration->Release();
	}
	if (g_pTexture != NULL) {
		g_pTexture->Release();
	}
	if (g_pd3dDevice != NULL) {
		g_pd3dDevice->Release();
	}
	if (g_pD3D != NULL) {
		g_pD3D->Release();
	}
}

bool InitGeometry() {
    void *pVerts;
	//The quad, this is more or less what you already have
    if (FAILED(g_pd3dDevice->CreateVertexBuffer(sizeof(aQuad), 0, D3DFVF_PICVERTEX, D3DPOOL_DEFAULT, &g_pQuadVB, NULL))) {
        return false;
    }
    if (FAILED(g_pQuadVB->Lock(0, 0, &pVerts, 0))) {
        return false;
	}
	memcpy(pVerts, aQuad, sizeof(aQuad));
    g_pQuadVB->Unlock();
	if (FAILED(D3DXCreateTextureFromFile(g_pd3dDevice, "demo.bmp", &g_pTexture))) {
		MessageBox(HWND_DESKTOP, _T("Place an image named \'demo.bmp\' in the working directory to have a textured plane."), _T("No texture"), MB_OK | MB_ICONWARNING);
		//return false;
	}
	//single pixel points, pretty much the same as the quad you already had
    if (FAILED(g_pd3dDevice->CreateVertexBuffer(sizeof(g_colPixels), 0, D3DFVF_PIXELVERTEX, D3DPOOL_DEFAULT, &g_pPixelVB, NULL))) {
        return false;
    }
    if (FAILED(g_pPixelVB->Lock(0, 0, &pVerts, 0))) {
        return false;
	}
	memcpy(pVerts, g_colPixels, sizeof(g_colPixels));
    g_pPixelVB->Unlock();
	//any size point, pretty much the same as the quad you already had
    if (FAILED(g_pd3dDevice->CreateVertexBuffer(sizeof(g_colPoints), 0, D3DFVF_POINTVERTEX, D3DPOOL_DEFAULT, &g_pPointVB, NULL))) {
        return false;
    }
    if (FAILED(g_pPointVB->Lock(0, 0, &pVerts, 0))) {
        return false;
	}
	memcpy(pVerts, g_colPoints, sizeof(g_colPoints));
    g_pPointVB->Unlock();
    return true;
}

void SetupMatrices() {
	//You will probably have a function similar to this somewhere. This builds the matrices for World, View and Projection
	D3DXMATRIXA16 matWorld, matView, matProj, matTmp;
	D3DXMatrixRotationZ(&matWorld, timeGetTime() / 1000.0f);
	//D3DXMatrixRotationX(&matTmp, timeGetTime() / 10000.0f);
	//matWorld *= matTmp;
	g_pd3dDevice->SetTransform(D3DTS_WORLD, &matWorld);
	D3DXVECTOR3 vEyePt(0.0f, -3.0f, -4.0f);
	D3DXVECTOR3 vLookatPt(0.0f, 0.0f, 0.0f);
	D3DXVECTOR3 vUpVec(0.0f, 1.0f, 0.0f);
	D3DXMatrixLookAtLH(&matView, &vEyePt, &vLookatPt, &vUpVec);
	g_pd3dDevice->SetTransform(D3DTS_VIEW, &matView);
	D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI / 4, 1.0f, 1.0f, 100.0f);
	g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &matProj);
	//This passes the projection matrix onto the shader, you will need to add this to your code
	if (g_pEffect != NULL) {
		D3DXMATRIXA16 matWoldViewProj = matWorld * matView * matProj;
		g_pEffect->SetMatrix("matWorldViewProj", &matWoldViewProj);
	}
}

void Render() {
	g_pd3dDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
	if (SUCCEEDED(g_pd3dDevice->BeginScene())) {
		SetupMatrices();
		//Render the image first. Because we are not using a depth buffer, whatever we render last will appear on top
		g_pd3dDevice->SetTexture(0, g_pTexture); //Set your texture
		g_pd3dDevice->SetStreamSource(0, g_pQuadVB, 0, sizeof(PicVertex));
		g_pd3dDevice->SetFVF(D3DFVF_PICVERTEX);
		g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
		//Now render the multi-pixel points on top of that
		g_pd3dDevice->SetStreamSource(0, g_pPointVB, 0, sizeof(PointVertex));
		if (g_pEffect == NULL) { //we dont have a shader, render using the fixed function pipeline
			g_pd3dDevice->SetTexture(0, NULL); //Set your texture
			g_pd3dDevice->SetFVF(D3DFVF_POINTVERTEX);
			g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, (sizeof(g_colPoints) / sizeof(g_colPoints[0])) / 3);
		} else {
			g_pd3dDevice->SetVertexDeclaration(g_pVertexDeclaration);
			g_pEffect->SetTechnique(g_pPointEffect);
			UINT nPasses; //Our effect only has 1 pass, P0, so the following for loop will only have 1 itteration
			g_pEffect->Begin(&nPasses, 0);
			for (UINT nPass = 0; nPass < nPasses; ++nPass) {
				g_pEffect->BeginPass(nPass);
				g_pd3dDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, (sizeof(g_colPoints) / sizeof(g_colPoints[0])) / 3);
				g_pEffect->EndPass();
			}
			g_pEffect->End();
			g_pEffect->SetTechnique(g_pFFEffect);
			g_pd3dDevice->SetVertexDeclaration(NULL);
		}
		//And finally the pixel on top of it
		g_pd3dDevice->SetFVF(D3DFVF_PIXELVERTEX);
		g_pd3dDevice->SetStreamSource(0, g_pPixelVB, 0, sizeof(PixelVertex));
		g_pd3dDevice->DrawPrimitive(D3DPT_POINTLIST, 0, sizeof(g_colPixels) / sizeof(PixelVertex));
		g_pd3dDevice->EndScene();
	}
	g_pd3dDevice->Present(NULL, NULL, NULL, NULL);
}

LRESULT WINAPI MsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
	//Nothing special here
	switch (msg) {
		case WM_DESTROY:
			Cleanup();
			PostQuitMessage(0);
			return 0;
	}
	return DefWindowProc(hWnd, msg, wParam, lParam);
}

int WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
	//Nothing special here
	WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0, 0, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, _T("DotsExample"), NULL };
	RegisterClassEx(&wc);
	HWND hWnd = CreateWindow(_T("DotsExample"), _T("Points Example - Andrew Brock"), WS_OVERLAPPEDWINDOW, 100, 100, 580, 580, NULL, NULL, wc.hInstance, NULL);
	if (InitD3D(hWnd)) {
        if (InitGeometry()) {
            ShowWindow(hWnd, SW_SHOWDEFAULT);
            UpdateWindow(hWnd);
            MSG msg;
            ZeroMemory(&msg, sizeof(msg));
            while (msg.message != WM_QUIT) {
                if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
                    TranslateMessage(&msg);
                    DispatchMessage(&msg);
                } else {
                    Render();
				}
            }
        }
    }
    UnregisterClass(_T("DotsExample"), wc.hInstance);
    return 0;
}


Shader.fx:
C++
float4x4 matWorldViewProj : WORLDVIEWPROJ; //World * View * Projection, passed in from SetupMatrices()

//What our vertex shader outputs, and the input of our pixel shader
struct VS_OUTPUT {
    float4 vPosition : POSITION;
    float4 vDiffuse : COLOR;
	float2 vTexCoord : TEXCOORD0;
};

//This is the vertex shader. It is called once for each vertex in our mesh (a quad).
//This neads to convert the mesh co-ordinate of the vertex into the screen co-ordinate.
//This is done by multiplying the position by the World x View x Projection matrices
//The output from this is then used to determine what pixels to draw, and is then fed into the Pixel Shader.
VS_OUTPUT VertexShaderPoint(float4 vPos : POSITION, float4 vDiffuse : COLOR, float2 vTexCoord : TEXCOORD0) {
	VS_OUTPUT output;
	output.vPosition = mul(vPos, matWorldViewProj); //Multiply by world, view and projection matrices and pass onto pixel shader
	output.vDiffuse = vDiffuse; //Pass this straight onto the pixel shader
	output.vTexCoord = vTexCoord; //Pass this straight onto the pixel shader
	return output;
}

//This is the pixel shader. It is called once for each pixel drawn to screen in our custom point
//The output of this function is the coulour and alpha of the pixel to render to the screen.
float4 PixelShaderPoint(VS_OUTPUT input) : COLOR {
	//Imagine we have a circle, centered around (0.5, 0.5), and ranges from 0-1 in each dimension
	float2 len = input.vTexCoord - 0.5;
	//Now now we have a unit circle. That is a circle centered at (0, 0) and has a constant radius of 1 unit.
	//If the distance from this pixel to the center (0, 0) is more than 1, then this pixel lies outside of the circle, and hence should not be drawn
	//Otherwise if it is less than or equal to 1 then this pixel is part of the circle that makes up the point.
	//The issue here is that the distance formula has a square root in it, which is slow. We can cheat and use distance squared, and take into acount the squared lenght when comparing.
	//However, 1*1=1, so in this particular case, there is no difference
	float dist = len.x * len.x + len.y * len.y; //This is the square of the length from the center
	clip(0.25 - dist); //if the distance from the center of the square is >1 then dont render this pixel
	return input.vDiffuse;
}

//This is the technique we use for rendering. It tells the graphics card what vertex and pixel shaders to use.
//We can also use it to set the render state to do things like enable/disable alpha blending, depth, ...
technique Point {
	pass P0 {
		VertexShader = compile vs_2_0 VertexShaderPoint();
		PixelShader = compile ps_2_0 PixelShaderPoint();
	}
}

//This technique disables the custom shaders and hence re-enables the Fixed Function Pipeline
technique FixedFunction {
	pass P0 {
		VertexShader = NULL;
		PixelShader = NULL;
	}
}
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900