I'm having a problem with specular reflection. It flickers as I move around my object.
Sometimes
when I'm looking at a face, and I swivel the camera just a few degrees,
I get specular reflection. When I swivel a few more, the reflection is
gone - leading to the flicker.
But specular reflection is only
based on the position of the camera, not the direction it's looking.
So it confuses me that swiveling the camera would change the specular
reflection in any way, much less so drastically.
Also, I find it confusing that I should see specular reflection at all from a face that receives no direct light.
It seems to only happen to
faces whose normal is perfectly perpendicular to the direction of the
light.
I'd be very grateful if someone could help me solve this problem. I've been at it for days, and it's driving me insane.
Thanks

Specular reflections aren't working right
Brent Lee
The light direction is [1,0,0].
I've tinkered with the power and specular color settings and I still see flicker. But it still doesn't seem right that you should see any specular reflection at all since the camera can't be at any position where direct light will be reflected back to the camera.
PCU
So kudos to you, because you're the only one on any of the forums that knew the answer and helped me out. Thanks.
Jay McG
Bruce MacKenzie
But as I said, just pushing the power value to 15.0f solved the issue...
Rohit Wason
jslapp
D3DMATERIAL9 m;
::ZeroMemory(&m, sizeof(m));
m.Specular.a = m.Specular.b = m.Specular.g = m.Specular.r = 1.0f;
m.Power = 15.0f;
I still see the same problem.
Did you see the issue before you changed the power setting
McLean Schofield - MSFT
Could you post the corrected code you used that fixed the problem
Santiago Cepas Lopez
Ok, here's the functions that changed (had to play a little with the Animate function to increase interaction rate)...
HRESULT CALLBACK DeviceReset( IDirect3DDevice9* pDevice, const D3DSURFACE_DESC* surface, void* )
{
pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
pDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
pDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
RecalcLook(pDevice);
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj,
D3DX_PI / 4,
(float)surface->Width / (float)surface->Height,
1.0f,
1000.0f);
pDevice->SetTransform(D3DTS_PROJECTION, &proj);
D3DLIGHT9 l;
::ZeroMemory(&l, sizeof(l));
l.Type = D3DLIGHT_DIRECTIONAL;
l.Ambient.a = l.Ambient.b = l.Ambient.g = l.Ambient.r = 1.0f;
l.Diffuse = l.Ambient;
l.Specular = l.Ambient;
l.Direction = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
pDevice->SetLight(0, &l);
pDevice->LightEnable(0, TRUE);
D3DMATERIAL9 m;
::ZeroMemory(&m, sizeof(m));
m.Specular.a = m.Specular.b = m.Specular.g = m.Specular.r = 1.0f;
m.Power = 15.0f;
pDevice->SetMaterial(&m);
return S_OK;
}
void CALLBACK Animate( IDirect3DDevice9* pDevice, double, float, void* )
{
float old = g_rot;
if ( GetAsyncKeyState(VK_LCONTROL) & 0x800f ) {
if ( GetAsyncKeyState('A') & 0x800f ) {
g_rx -= 0.011f;
}
if ( GetAsyncKeyState('D') & 0x800f ) {
g_rx += 0.011f;
}
if ( GetAsyncKeyState('W') & 0x800f ) {
g_ry += 0.011f;
}
if ( GetAsyncKeyState('S') & 0x800f ) {
g_ry -= 0.011f;
}
g_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
g_up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
g_look = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
D3DXMATRIX m;
D3DXMatrixRotationAxis(&m, &g_up, g_rx);
D3DXVec3TransformCoord(&g_right, &g_right, &m);
D3DXVec3TransformCoord(&g_look, &g_look, &m);
D3DXMatrixRotationAxis(&m, &g_right, g_ry);
D3DXVec3TransformCoord(&g_up, &g_up, &m);
D3DXVec3TransformCoord(&g_look, &g_look, &m);
RecalcLook(pDevice);
}
else {
if ( GetAsyncKeyState('A') & 0x800f ) {
g_pos -= g_right * 0.01f;
RecalcLook(pDevice);
}
if ( GetAsyncKeyState('D') & 0x800f ) {
g_pos += g_right * 0.01f;
RecalcLook(pDevice);
}
if ( GetAsyncKeyState('W') & 0x800f) {
if (GetAsyncKeyState(VK_LSHIFT) & 0x800f) {
g_pos += g_up * 0.01f;
RecalcLook(pDevice);
}
else {
g_pos += g_look * 0.01f;
RecalcLook(pDevice);
}
}
if ( GetAsyncKeyState('S') & 0x800f) {
if (GetAsyncKeyState(VK_LSHIFT) & 0x800f) {
g_pos -= g_up * 0.01f;
RecalcLook(pDevice);
}
else {
g_pos -= g_look * 0.01f;
RecalcLook(pDevice);
}
}
}
if ( GetAsyncKeyState(VK_RIGHT) ) {
g_rot += 0.011f;
}
if ( GetAsyncKeyState(VK_LEFT) ) {
g_rot -= 0.011f;
}
if (g_rot != old) {
D3DXMATRIX m;
D3DXMatrixRotationY(&m, g_rot);
pDevice->SetTransform(D3DTS_WORLD, &m);
}
}
BlakeW
#include <windows.h>
#include <d3d9.h>
#include <d3dx9.h>
#include <dxut.h>
struct VERTEX {
float x, y, z;
float nx, ny, nz;
};
#define VERTEX_FVF (D3DFVF_XYZ | D3DFVF_NORMAL)
IDirect3DVertexBuffer9* g_pVB;
float g_rot = 0.0f;
D3DXVECTOR3 g_pos(-5.0f, 0.0f, 0.0f);
D3DXVECTOR3 g_right(0.0f, 0.0f, -1.0f);
D3DXVECTOR3 g_up(0.0f, 1.0f, 0.0f);
D3DXVECTOR3 g_look(1.0f, 0.0f, 0.0f);
float g_rx = D3DX_PI / 2;
float g_ry = 0.0f;
HRESULT CALLBACK DeviceCreated( IDirect3DDevice9* pDevice, const D3DSURFACE_DESC* surface, void* )
{
VERTEX vertices[] = {
// front
{ -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f },
{ -1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f },
{ 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f },
{ -1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f },
{ 1.0f, 1.0f, -1.0f, 0.0f, 0.0f, -1.0f },
{ 1.0f, -1.0f, -1.0f, 0.0f, 0.0f, -1.0f },
// left size
{ -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f },
{ -1.0f, 1.0f, 1.0f, -1.0f, 0.0f, 0.0f },
{ -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f },
{ -1.0f, -1.0f, 1.0f, -1.0f, 0.0f, 0.0f },
{ -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 0.0f },
{ -1.0f, -1.0f, -1.0f, -1.0f, 0.0f, 0.0f },
};
pDevice->CreateVertexBuffer(sizeof(vertices), D3DUSAGE_WRITEONLY, VERTEX_FVF, D3DPOOL_MANAGED, &g_pVB, NULL);
VERTEX* pBuffer;
g_pVB->Lock(0, 0, reinterpret_cast<void**>(&pBuffer), 0);
memcpy(pBuffer, vertices, sizeof(vertices));
g_pVB->Unlock();
return S_OK;
}
void RecalcLook(IDirect3DDevice9* pDevice)
{
D3DXVec3Normalize(&g_look, &g_look);
D3DXVec3Cross(&g_up, &g_look, &g_right);
D3DXVec3Normalize(&g_up, &g_up);
D3DXVec3Cross(&g_right, &g_up, &g_look);
D3DXVec3Normalize(&g_right, &g_right);
float x = -D3DXVec3Dot(&g_right, &g_pos);
float y = -D3DXVec3Dot(&g_up, &g_pos);
float z = -D3DXVec3Dot(&g_look, &g_pos);
D3DXMATRIX view;
view(0, 0) = g_right.x;
view(0, 1) = g_up.x;
view(0, 2) = g_look.x;
view(0, 3) = 0.0f;
view(1, 0) = g_right.y;
view(1, 1) = g_up.y;
view(1, 2) = g_look.y;
view(1, 3) = 0.0f;
view(2, 0) = g_right.z;
view(2, 1) = g_up.z;
view(2, 2) = g_look.z;
view(2, 3) = 0.0f;
view(3, 0) = x;
view(3, 1) = y;
view(3, 2) = z;
view(3, 3) = 1.0f;
pDevice->SetTransform(D3DTS_VIEW, &view);
}
HRESULT CALLBACK DeviceReset( IDirect3DDevice9* pDevice, const D3DSURFACE_DESC* surface, void* )
{
pDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
pDevice->SetRenderState(D3DRS_NORMALIZENORMALS, TRUE);
pDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
pDevice->SetRenderState(D3DRS_SPECULARMATERIALSOURCE, D3DMCS_MATERIAL);
RecalcLook(pDevice);
D3DXMATRIX proj;
D3DXMatrixPerspectiveFovLH(
&proj,
D3DX_PI / 4,
(float)surface->Width / (float)surface->Height,
1.0f,
1000.0f);
pDevice->SetTransform(D3DTS_PROJECTION, &proj);
D3DLIGHT9 l;
::ZeroMemory(&l, sizeof(l));
l.Type = D3DLIGHT_DIRECTIONAL;
l.Ambient.a = l.Ambient.b = l.Ambient.g = l.Ambient.r = 1.0f;
l.Diffuse = l.Ambient;
l.Specular = l.Ambient;
l.Direction = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
pDevice->SetLight(0, &l);
pDevice->LightEnable(0, TRUE);
D3DMATERIAL9 m;
::ZeroMemory(&m, sizeof(m));
m.Specular.a = m.Specular.b = m.Specular.g = m.Specular.r = 1.0f;
m.Power = 5.0f;
pDevice->SetMaterial(&m);
return S_OK;
}
void CALLBACK DeviceDestroyed(void*)
{
g_pVB->Release();
}
void CALLBACK Animate( IDirect3DDevice9* pDevice, double, float, void* )
{
float old = g_rot;
if ( GetAsyncKeyState(VK_LCONTROL) & 0x800f ) {
if ( GetAsyncKeyState('A') & 0x800f ) {
g_rx -= 0.001f;
}
if ( GetAsyncKeyState('D') & 0x800f ) {
g_rx += 0.001f;
}
if ( GetAsyncKeyState('W') & 0x800f ) {
g_ry += 0.001f;
}
if ( GetAsyncKeyState('S') & 0x800f ) {
g_ry -= 0.001f;
}
g_right = D3DXVECTOR3(1.0f, 0.0f, 0.0f);
g_up = D3DXVECTOR3(0.0f, 1.0f, 0.0f);
g_look = D3DXVECTOR3(0.0f, 0.0f, 1.0f);
D3DXMATRIX m;
D3DXMatrixRotationAxis(&m, &g_up, g_rx);
D3DXVec3TransformCoord(&g_right, &g_right, &m);
D3DXVec3TransformCoord(&g_look, &g_look, &m);
D3DXMatrixRotationAxis(&m, &g_right, g_ry);
D3DXVec3TransformCoord(&g_up, &g_up, &m);
D3DXVec3TransformCoord(&g_look, &g_look, &m);
RecalcLook(pDevice);
}
else {
if ( GetAsyncKeyState('A') & 0x800f ) {
g_pos -= g_right * 0.01f;
RecalcLook(pDevice);
}
if ( GetAsyncKeyState('D') & 0x800f ) {
g_pos += g_right * 0.01f;
RecalcLook(pDevice);
}
if ( GetAsyncKeyState('W') & 0x800f) {
if (GetAsyncKeyState(VK_LSHIFT) & 0x800f) {
g_pos += g_up * 0.01f;
RecalcLook(pDevice);
}
else {
g_pos += g_look * 0.01f;
RecalcLook(pDevice);
}
}
if ( GetAsyncKeyState('S') & 0x800f) {
if (GetAsyncKeyState(VK_LSHIFT) & 0x800f) {
g_pos -= g_up * 0.01f;
RecalcLook(pDevice);
}
else {
g_pos -= g_look * 0.01f;
RecalcLook(pDevice);
}
}
}
if ( GetAsyncKeyState(VK_RIGHT) ) {
g_rot += 0.001f;
}
if ( GetAsyncKeyState(VK_LEFT) ) {
g_rot -= 0.001f;
}
if (g_rot != old) {
D3DXMATRIX m;
D3DXMatrixRotationY(&m, g_rot);
pDevice->SetTransform(D3DTS_WORLD, &m);
}
}
void CALLBACK Render( IDirect3DDevice9* pDevice, double, float, void* )
{
pDevice->Clear(0, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_TARGET, D3DCOLOR_ARGB(255, 0, 0, 0), 1.0f, 0);
pDevice->BeginScene();
pDevice->SetFVF(VERTEX_FVF);
pDevice->SetStreamSource(0, g_pVB, 0, sizeof(VERTEX));
pDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, 4);
pDevice->EndScene();
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, INT cmdShow)
{
DXUTInit();
DXUTSetCallbackDeviceCreated(DeviceCreated);
DXUTSetCallbackDeviceDestroyed(DeviceDestroyed);
DXUTSetCallbackFrameRender(Render);
DXUTSetCallbackDeviceReset(DeviceReset);
DXUTSetCallbackFrameMove(Animate);
DXUTCreateWindow();
DXUTCreateDevice();
DXUTMainLoop();
}
SB1000
Are you using fixed function lighting If you use a shader it were useful if you could post some code.
Just a guess: maybe your normals are not correct or you don't transform them correctly.