Archived

This topic is now archived and is closed to further replies.

Coleco

Newbie: How would I do this??

Recommended Posts

3D newbie here. I am using 3D textured quads for a 2D engine (tile based) Tile are drawing fine but I want to experiment with lighting. What I want to do is say have my player walk into a cave with torches and everything is completely black until it comes near a torch... I have no idea how to start somthing like this... Suggestions appreciated. Thanks! -cbmeeks

~ c o l ec o ~

Rock the cradle of love! You stupid WANKER! S i g n a l D E V .com Metroid Classic

Share this post


Link to post
Share on other sites
There is hardware lighting in DirectX, but I haven't tried using it myself, yet.

If you want to do it in software, then make sure that your vertex structure includes a D3DCOLOR diffuse value (and adjust your FVF accordingly, of course). Then you can use SetTextureStageState to blend the texture with the vertex color. You'd probably use MODULATE as the operation, use TEXTURE as ARG1, and DIFFUSE as ARG2. Then, before you draw your quad, just make sure that the color values for the vertices are set. White would make the textures show up normally. Black would make them completely black. Blue would filter out all red and green, etc. There are other operations besides MODULATE that you can use too, if you want to brighten a texture beyond its typical brightness, or to maybe even get odd effects.

So the only thing left would be to calculate which tiles need to have a darker color applied to them.

[Edit - I was missing the word "FVF". Dunno how.]

[edited by - Agony on May 25, 2004 11:43:47 AM]

Share this post


Link to post
Share on other sites
dx8: you''ll want to do a m_pD3DDevice->SetMaterial(&mtrl), along with m_pD3DDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB(ar, ag, ab). After that, m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE).

then for each light:
m_pD3DDevice->SetLight(0through7, &d3dLight);
m_pD3DDevice->LightEnable(0through7, TRUE);

once you''re out of the caves all yuo need is to set the ambient light back to 255,255,255.

Share this post


Link to post
Share on other sites
quote:
Original post by kVandaele
oh, and be aware that lights are very expensive. Especially for a 2d game I''d suggest no more than 1-2 lights. The light you''ll most likely want is a point light.

Hm.. 1 - 2 lights? Are you sure that lights are THAT expensive?

I don''t think so.

--
You''re Welcome,
Rick Wong
- Google | Google for GameDev.net | GameDev.net''s DirectX FAQ. (not as cool as the Graphics and Theory FAQ)

Share this post


Link to post
Share on other sites
Most documents or books I''ve read on lighting say that the first 8 to 10 lights come pretty much free on today''s video cards. Spotlights are expensive, point lights are less, and directional lights are the least. I would think in your case though, you only need 1 light, the one in the player''s (his character''s) hand...unless you put torches on the walls. You might as well use a light map if you''re going to do that though, since the torch won''t be moving (unless you animate the flame).

Chris

Share this post


Link to post
Share on other sites
Yeah, I just can''t seem to get the spotlight to work. Every variation of lighting I do just acts as ambient light. No matter what direction, type, etc it affects everything.

I am thinking because my quads obviously just have two triangles so you can''t do detailed vertex lighting...

Ok, I''ve been hearing light maps...how would I go about doing that? Any good sites? Remember, I am doing 2D with quads...thanks!

-cbmeeks

~ c o l ec o ~



Rock the cradle of love!
You stupid WANKER!
S i g n a l D E V .com
Metroid Classic

Share this post


Link to post
Share on other sites
quote:
Original post by Pipo DeClown
Hm.. 1 - 2 lights? Are you sure that lights are THAT expensive?

I don''t think so.



while true, I don''t think a 2d game is aimed at today''s video cards, nor is it good for a 2d game to have a recent video card as minimum requirements...

Coleco: have you tried reducing the range and/or brightness of the point light? Also, try and make it blue and see if the screen turns blue. If not you forgot to set something (the material, some states, ...)

Share this post


Link to post
Share on other sites
we''ll you''ll want to set the light right above the quad, and have the range be small. The further away, the less the change across the screen will be...

maybe you could post the code you used to create your lights/quad

Share this post


Link to post
Share on other sites
Here is my code:

QUADS

//---------------------------------------------------------------------------------

// Constructor

//---------------------------------------------------------------------------------

CSprite_QUAD::CSprite_QUAD(IDirect3DDevice9 *Device, //D3D Device

D3DPRESENT_PARAMETERS pPresent, //D3D Present

CTexture_D3DX *pTexture, //Texture

int fwidth, //Width of FRAME

int fheight) //Height of FRAME

{

VB_BUFFER_SIZE = 4; // size of the vertext buffer

d3dDevice = Device; // grab the D3D Device

texture = pTexture->GetTexture(); // grab the texture


//color key

D3DCOLOR colorkey = 0xFFFF00FF;

//Create vertex buffer and set as stream source

d3dDevice->CreateVertexBuffer( sizeof(TLVERTEX) * VB_BUFFER_SIZE,
D3DUSAGE_WRITEONLY, //write only..faster

D3DFVF_TLVERTEX, //FVF format

D3DPOOL_MANAGED, //DirectX manages memory

&VB, //Vertex buffer

NULL );


//Lock the vertex buffer and set default color and other stuff

VB->Lock(0, 0, (void **)&vertices, NULL);

//Setup vertices

vertices[0].color = 0xFFFFFFFF;
vertices[1].color = 0xFFFFFFFF;
vertices[2].color = 0xFFFFFFFF;
vertices[3].color = 0xFFFFFFFF;

vertices[0].x = 0.0f;
vertices[0].y = 0.0f;

vertices[1].x = 1.0f;
vertices[1].y = 0.0f;

vertices[2].x = 1.0f;
vertices[2].y = -1.0f;

vertices[3].x = 0.0f;
vertices[3].y = -1.0f;


//Unlock the vertex buffer

VB->Unlock();



//Set stream source to vertex buffer

d3dDevice->SetStreamSource(0, VB, 0, sizeof(TLVERTEX));

//get texture surface description

texture->GetLevelDesc(0, &surfaceDesc);
tex_width = surfaceDesc.Width;
tex_height = surfaceDesc.Height;

//setup dimensions

FrameWidth = fwidth;
FrameHeight = fheight;
NumFramesWide = tex_width / FrameWidth;
NumFramesTall = tex_height / FrameHeight;
U = 1.0f / (float)NumFramesWide;
V = 1.0f / (float)NumFramesTall;

//Setup destination rectangle

rDest.left = x;
rDest.right = x + tex_width;
rDest.top = y;
rDest.bottom = y + tex_height;

//other variables

scr_width = pPresent.BackBufferWidth;
scr_height = pPresent.BackBufferHeight;

// set the texture

d3dDevice->SetTexture(0, texture);

//Defaults

x = 0;
y = 0;
CurrentFrame = 0;
xspeed = 0;
yspeed = 0;
rotation = 0.0f;
BorderState = BOUNCE;

}

//---------------------------------------------------------------------------------

// Destructor

//---------------------------------------------------------------------------------

CSprite_QUAD::~CSprite_QUAD()
{

//free resources

if(!VB == NULL) VB->Release();
if(!texture == NULL) texture->Release();

}

//---------------------------------------------------------------------------------

// Move

//---------------------------------------------------------------------------------

int CSprite_QUAD::Move()
{
x += xspeed;
y += yspeed;

switch(BorderState)
{

case BOUNCE:
{
if(x <= MinXPos) xspeed = -xspeed;
if(x >= MaxXPos) xspeed = -xspeed;
if(y <= MinYPos) yspeed = -yspeed;
if(y >= MaxYPos) yspeed = -yspeed;
}
break;

case WRAP:
{
if(x <= MinXPos) x = MaxXPos;
if(x >= MaxXPos) x = MinXPos;
if(y <= MinYPos) y = MaxYPos;
if(y >= MaxYPos) y = MinYPos;
}
break;

}

return true;
}

//---------------------------------------------------------------------------------

// Draw

//---------------------------------------------------------------------------------

int CSprite_QUAD::Draw()
{
float X;
float Y;


//Get coordinates

rDest.left = x;
rDest.top = y;
rDest.right = x + FrameWidth;
rDest.bottom = y + FrameHeight;

X = rDest.left - (float)(scr_width) / 2;
Y = -rDest.top + (float)(scr_height) / 2;

rfSource.top = ( CurrentFrame / NumFramesWide ) * V;
rfSource.left = ( CurrentFrame % NumFramesTall ) * V;
rfSource.bottom = rfSource.top + V;
rfSource.right = rfSource.left + U;

//Lock the vertex buffer

VB->Lock(0, 0, (void **)&vertices, NULL);

//Setup vertices in buffer


//top left

vertices[0].z = 1.0f;
vertices[0].u = rfSource.left;
vertices[0].v = rfSource.top;

//top right

vertices[1].z = 1.0f;
vertices[1].u = rfSource.right;
vertices[1].v = rfSource.top;

//bottom right

vertices[2].z = 1.0f;
vertices[2].u = rfSource.right;
vertices[2].v = rfSource.bottom;

//bottom left

vertices[3].z = 1.0f;
vertices[3].u = rfSource.left;
vertices[3].v = rfSource.bottom;


//Setup translation and scaling matrices

D3DXMatrixScaling( &matScaling,
(float)(rDest.right - rDest.left),
(float)(rDest.bottom - rDest.top),
1.0f ); // scales the sprite


D3DXMatrixTranslation (&matTranslation, X, Y, 0.0f); // moves the sprite

matTransform = matScaling * matTranslation;

//Check if quad is rotated

if(rotation)
{
D3DXMATRIX matRotate;

//Create rotation matrix about the z-axis

D3DXMatrixRotationZ (&matRotate, rotation);

//Multiply matrices together

matTransform *= matRotate;
}

//Set world matrix to an identity matrix

d3dDevice->SetTransform(D3DTS_WORLD, &matTransform);


//Unlock vertex buffer

VB->Unlock();

//Set texture

d3dDevice->SetTexture(0, texture);

//Set stream source to vertex buffer

d3dDevice->SetStreamSource(0, VB, 0, sizeof(TLVERTEX));

//Draw image

d3dDevice->DrawPrimitive (D3DPT_TRIANGLEFAN, 0, 2);

return true;
}


//---------------------------------------------------------------------------------

// SetColor

//---------------------------------------------------------------------------------

int CSprite_QUAD::SetColor(D3DCOLOR aColor)
{
//Lock the vertex buffer

VB->Lock(0, 0, (void **)&vertices, NULL);

//Setup vertices

vertices[0].color = aColor;
vertices[1].color = aColor;
vertices[2].color = aColor;
vertices[3].color = aColor;

//Unlock the vertex buffer

VB->Unlock();

return true;
}


//---------------------------------------------------------------------------------

// SetCorner0

//---------------------------------------------------------------------------------

int CSprite_QUAD::AdjustVertex( float x0, float y0,
float x1, float y1,
float x2, float y2,
float x3, float y3 )

{

//Adding to Y coords moves the vertex UP


//Lock the vertex buffer

VB->Lock(0, 0, (void **)&vertices, NULL);

vertices[0].x = x0;
vertices[0].y = y0;

vertices[1].x = x1;
vertices[1].y = y1;

vertices[2].x = x2;
vertices[2].y = y2;

vertices[3].x = x3;
vertices[3].y = y3;

//Unlock the vertex buffer

VB->Unlock();

return true;
}


//---------------------------------------------------------------------------------

// Properties

//---------------------------------------------------------------------------------

CSprite_QUAD::SetX(int xx)
{
x = xx;
}
CSprite_QUAD::SetY(int yy)
{
y = yy;
}
CSprite_QUAD::SetXSpeed(int xs)
{
xspeed = xs;
}
CSprite_QUAD::SetYSpeed(int ys)
{
yspeed = ys;
}
CSprite_QUAD::SetFrame(int cf)
{
CurrentFrame = cf;
}
CSprite_QUAD::SetRotation(float ang) // sets the rotation angle

{
rotation = ang;
}
CSprite_QUAD::SetMinXPos(int mx)
{
MinXPos = mx;
}
CSprite_QUAD::SetMinYPos(int my)
{
MinYPos = my;
}
CSprite_QUAD::SetMaxXPos(int mx)
{
MaxXPos = mx;
}
CSprite_QUAD::SetMaxYPos(int my)
{
MaxYPos = my;
}
CSprite_QUAD::SetBorderState(int state)
{
BorderState = state;
}






LIGHTS


//---------------------------------------------------------------------------------

// Constructor

//---------------------------------------------------------------------------------

CLights::CLights( IDirect3DDevice9 *Device, // d3d device

D3DCAPS9 Caps, // capabilities of graphics adapter

CLog log, // Log File

float r, // red

float g, // green

float b, // blue

float a) // ambience

{
d3dDevice = Device; // grab the D3D Device

d3dCaps = Caps; // grab the capabilities

Log = log; // grab the log file pointer


HRESULT hr;

// Set up a material

ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
mtrl.Diffuse.r = mtrl.Ambient.r = r;
mtrl.Diffuse.g = mtrl.Ambient.g = g;
mtrl.Diffuse.b = mtrl.Ambient.b = b;
mtrl.Diffuse.a = mtrl.Ambient.a = a;
d3dDevice->SetMaterial( &mtrl );


D3DLIGHT9 light;
D3DXVECTOR3 vecDir;
ZeroMemory( &light, sizeof(D3DLIGHT9) );
light.Type = D3DLIGHT_SPOT;

light.Diffuse.r = 1.0f;
light.Diffuse.g = 0.0f;
light.Diffuse.b = 0.0f;

light.Ambient.r = 0.0f;
light.Ambient.g = 0.0f;
light.Ambient.b = 0.0f;

light.Direction.x = 0.0f; //tried diff values here

light.Direction.y = -10.0f; //tried diff values here

light.Direction.z = 10.0f; //tried diff values here


light.Attenuation0 = 1.0f;
light.Attenuation1 = 0.0f;
light.Attenuation2 = 0.0f;

light.Falloff = 0.0f;
light.Phi = 0.5f;
light.Theta = 1.0f;

light.Range = 10.0f;

vecDir = D3DXVECTOR3(0,5,0);

D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecDir );

d3dDevice->SetLight( 0, &light );
d3dDevice->LightEnable(0, TRUE );

}


-cbmeeks

~ c o l ec o ~



Rock the cradle of love!
You stupid WANKER!
S i g n a l D E V .com
Metroid Classic



[edited by - coleco on May 25, 2004 3:34:34 PM]

Share this post


Link to post
Share on other sites
Could you not do another quad for the light, that kinda goes on top of littable(is this a word?) objects, but goes behind unlittable(again?) objects.

If I''m correct, this is called Additive Blending.

--
You''re Welcome,
Rick Wong
- Google | Google for GameDev.net | GameDev.net''s DirectX FAQ. (not as cool as the Graphics and Theory FAQ)

Share this post


Link to post
Share on other sites
try ricks idea, use a single quad, for the texture you want a circular gradient that fades to nothing near the edges. obviously you''ll move that around with your player.

add a lighteable property to your other tiles and test for collision(2d box-box would prol be fine) if you find a collsion do the additive blend previously suggested.

I''ve used this in 3d, with a billboard to mimic a "flash grenade" effect and it turned out ok.

Dredd
________________________________________

"To die with your sword still in its sheath is most regrettable" -- Miyomoto Musashi


Share this post


Link to post
Share on other sites
quote:

I don''t see where you set the render state to enable lighting. Did you do that?

g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, TRUE );



Yes, I have it in my screen setup code.


Thanks guys, I will try and check that article out.

-cbmeeks

~ c o l ec o ~



Rock the cradle of love!
You stupid WANKER!
S i g n a l D E V .com
Metroid Classic

Share this post


Link to post
Share on other sites
That article is a bit too complex for this I think.. And quads of 2 triangles, don''t lit well in Direct3D. You need more if you want it to look good.

If you''d go for additive blending, you''d have this loop (pseudo-code):

Clear();
EnableTesting(); // Alpha Testing always on


// Layer 1

Draw();

// Layer 2

EnableBlending( ADDITIVE ); // Alpha Blending for the lights

Draw();

// Layer 3

DisableBlending(); // Disable Alpha Blending and draw the remaining things

Draw();


--
You''re Welcome,
Rick Wong
- Google | Google for GameDev.net | GameDev.net''s DirectX FAQ. (not as cool as the Graphics and Theory FAQ)

Share this post


Link to post
Share on other sites