Commit d70a2c03 authored by Lionel Ulmer's avatar Lionel Ulmer Committed by Alexandre Julliard

- beginning of Material and Light support for D3D7

- new rendering states supported
parent 825ad056
......@@ -166,6 +166,7 @@ struct IDirect3DExecuteBufferImpl
*/
#define MAX_TEXTURES 8
#define MAX_LIGHTS 16
struct IDirect3DDeviceImpl
{
......@@ -189,6 +190,13 @@ struct IDirect3DDeviceImpl
D3DMATRIX *view_mat;
D3DMATRIX *proj_mat;
/* Current material used in D3D7 mode */
D3DMATERIAL7 current_material;
/* Light parameters */
DWORD active_lights, set_lights;
D3DLIGHT7 light_parameters[MAX_LIGHTS];
void (*set_context)(IDirect3DDeviceImpl*);
HRESULT (*clear)(IDirect3DDeviceImpl *This,
DWORD dwCount,
......@@ -215,6 +223,9 @@ struct IDirect3DVertexBufferImpl
/* Various dump functions */
extern const char *_get_renderstate(D3DRENDERSTATETYPE type);
extern void dump_D3DMATERIAL7(LPD3DMATERIAL7 lpMat);
extern void dump_D3DCOLORVALUE(D3DCOLORVALUE *lpCol);
extern void dump_D3DLIGHT7(LPD3DLIGHT7 lpLight);
#define dump_mat(mat) \
TRACE("%f %f %f %f\n", (mat)->_11, (mat)->_12, (mat)->_13, (mat)->_14); \
......
......@@ -163,3 +163,44 @@ const char *_get_renderstate(D3DRENDERSTATETYPE type) {
if (type >= (sizeof(states) / sizeof(states[0]))) return "ERR";
return states[type];
}
void
dump_D3DCOLORVALUE(D3DCOLORVALUE *lpCol)
{
DPRINTF("%f %f %f %f", lpCol->u1.r, lpCol->u2.g, lpCol->u3.b, lpCol->u4.a);
}
void
dump_D3DVECTOR(D3DVECTOR *lpVec)
{
DPRINTF("%f %f %f", lpVec->u1.x, lpVec->u2.y, lpVec->u3.z);
}
void
dump_D3DMATERIAL7(LPD3DMATERIAL7 lpMat)
{
DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(lpMat->u.diffuse)); DPRINTF("\n");
DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(lpMat->u1.ambient)); DPRINTF("\n");
DPRINTF(" - specular : "); dump_D3DCOLORVALUE(&(lpMat->u2.specular)); DPRINTF("\n");
DPRINTF(" - emissive : "); dump_D3DCOLORVALUE(&(lpMat->u3.emissive)); DPRINTF("\n");
DPRINTF(" - power : %f\n", lpMat->u4.power);
}
void
dump_D3DLIGHT7(LPD3DLIGHT7 lpLight)
{
DPRINTF(" - light type : %s\n", (lpLight->dltType == D3DLIGHT_POINT ? "D3DLIGHT_POINT" :
(lpLight->dltType == D3DLIGHT_SPOT ? "D3DLIGHT_SPOT" :
(lpLight->dltType == D3DLIGHT_DIRECTIONAL ? "D3DLIGHT_DIRECTIONAL" :
"UNSUPPORTED"))));
DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(lpLight->dcvDiffuse)); DPRINTF("\n");
DPRINTF(" - specular : "); dump_D3DCOLORVALUE(&(lpLight->dcvSpecular)); DPRINTF("\n");
DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(lpLight->dcvAmbient)); DPRINTF("\n");
DPRINTF(" - position : "); dump_D3DVECTOR(&(lpLight->dvPosition)); DPRINTF("\n");
DPRINTF(" - direction : "); dump_D3DVECTOR(&(lpLight->dvDirection)); DPRINTF("\n");
DPRINTF(" - dvRange : %f\n", lpLight->dvRange);
DPRINTF(" - dvFalloff : %f\n", lpLight->dvFalloff);
DPRINTF(" - dvAttenuation : %f %f %f\n", lpLight->dvAttenuation0, lpLight->dvAttenuation1, lpLight->dvAttenuation2);
DPRINTF(" - dvTheta : %f\n", lpLight->dvTheta);
DPRINTF(" - dvPhi : %f\n", lpLight->dvPhi);
}
......@@ -162,7 +162,12 @@ Main_IDirect3DDeviceImpl_7_3T_2T_SetRenderTarget(LPDIRECT3DDEVICE7 iface,
DWORD dwFlags)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
FIXME("(%p/%p)->(%p,%08lx): stub!\n", This, iface, lpNewRenderTarget, dwFlags);
IDirectDrawSurfaceImpl *target_impl = ICOM_OBJECT(IDirectDrawSurfaceImpl, IDirectDrawSurface7, lpNewRenderTarget);
TRACE("(%p/%p)->(%p,%08lx)\n", This, iface, lpNewRenderTarget, dwFlags);
if (target_impl != This->surface) {
WARN(" Change of rendering target not handled yet !\n");
}
return DD_OK;
}
......@@ -307,7 +312,15 @@ Main_IDirect3DDeviceImpl_7_GetMaterial(LPDIRECT3DDEVICE7 iface,
LPD3DMATERIAL7 lpMat)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
FIXME("(%p/%p)->(%p): stub!\n", This, iface, lpMat);
TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
*lpMat = This->current_material;
if (TRACE_ON(ddraw)) {
TRACE(" returning material : \n");
dump_D3DMATERIAL7(lpMat);
}
return DD_OK;
}
......@@ -327,7 +340,16 @@ Main_IDirect3DDeviceImpl_7_GetLight(LPDIRECT3DDEVICE7 iface,
LPD3DLIGHT7 lpLight)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
FIXME("(%p/%p)->(%08lx,%p): stub!\n", This, iface, dwLightIndex, lpLight);
TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
*lpLight = This->light_parameters[dwLightIndex];
if (TRACE_ON(ddraw)) {
TRACE(" returning light : \n");
dump_D3DLIGHT7(lpLight);
}
return DD_OK;
}
......@@ -624,7 +646,13 @@ Main_IDirect3DDeviceImpl_7_GetLightEnable(LPDIRECT3DDEVICE7 iface,
BOOL* pbEnable)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
FIXME("(%p/%p)->(%08lx,%p): stub!\n", This, iface, dwLightIndex, pbEnable);
TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, pbEnable);
if (dwLightIndex > MAX_LIGHTS) *pbEnable = 0;
else *pbEnable = ((0x00000001 << dwLightIndex) & This->active_lights) != 0;
TRACE(" returning %d.\n", *pbEnable);
return DD_OK;
}
......
......@@ -538,6 +538,8 @@ GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
DWORD dwLightState)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice3, iface);
IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This;
TRACE("(%p/%p)->(%08x,%08lx)\n", This, iface, dwLightStateType, dwLightState);
switch (dwLightStateType) {
......@@ -553,17 +555,10 @@ GL_IDirect3DDeviceImpl_3_2T_SetLightState(LPDIRECT3DDEVICE3 iface,
}
} break;
case D3DLIGHTSTATE_AMBIENT: { /* 2 */
float light[4];
light[0] = ((dwLightState >> 16) & 0xFF) / 255.0;
light[1] = ((dwLightState >> 8) & 0xFF) / 255.0;
light[2] = ((dwLightState >> 0) & 0xFF) / 255.0;
light[3] = 1.0;
ENTER_GL();
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
LEAVE_GL();
} break;
case D3DLIGHTSTATE_AMBIENT: /* 2 */
/* Call the render_state function... */
set_render_state(D3DRENDERSTATE_AMBIENT, dwLightState, &(glThis->render_state));
break;
#define UNSUP(x) case D3DLIGHTSTATE_##x: FIXME("unsupported D3DLIGHTSTATE_" #x "!\n");break;
UNSUP(COLORMODEL);
......@@ -1469,6 +1464,103 @@ GL_IDirect3DDeviceImpl_7_GetCaps(LPDIRECT3DDEVICE7 iface,
return DD_OK;
}
HRESULT WINAPI
GL_IDirect3DDeviceImpl_7_SetMaterial(LPDIRECT3DDEVICE7 iface,
LPD3DMATERIAL7 lpMat)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
TRACE("(%p/%p)->(%p)\n", This, iface, lpMat);
if (TRACE_ON(ddraw)) {
TRACE(" material is : \n");
dump_D3DMATERIAL7(lpMat);
}
This->current_material = *lpMat;
glMaterialfv(GL_FRONT,
GL_DIFFUSE,
(float *) &(This->current_material.u.diffuse));
glMaterialfv(GL_FRONT,
GL_AMBIENT,
(float *) &(This->current_material.u1.ambient));
glMaterialfv(GL_FRONT,
GL_SPECULAR,
(float *) &(This->current_material.u2.specular));
glMaterialfv(GL_FRONT,
GL_EMISSION,
(float *) &(This->current_material.u3.emissive));
glMaterialf(GL_FRONT,
GL_SHININESS,
This->current_material.u4.power); /* Not sure about this... */
return DD_OK;
}
HRESULT WINAPI
GL_IDirect3DDeviceImpl_7_SetLight(LPDIRECT3DDEVICE7 iface,
DWORD dwLightIndex,
LPD3DLIGHT7 lpLight)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
TRACE("(%p/%p)->(%08lx,%p)\n", This, iface, dwLightIndex, lpLight);
if (TRACE_ON(ddraw)) {
TRACE(" setting light : \n");
dump_D3DLIGHT7(lpLight);
}
if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
This->set_lights |= 0x00000001 << dwLightIndex;
This->light_parameters[dwLightIndex] = *lpLight;
switch (lpLight->dltType) {
case D3DLIGHT_DIRECTIONAL: { /* 3 */
float direction[4];
glLightfv(GL_LIGHT0 + dwLightIndex, GL_AMBIENT, (float *) &(lpLight->dcvAmbient));
glLightfv(GL_LIGHT0 + dwLightIndex, GL_DIFFUSE, (float *) &(lpLight->dcvDiffuse));
glLightfv(GL_LIGHT0 + dwLightIndex, GL_SPECULAR, (float *) &(lpLight->dcvSpecular));
direction[0] = lpLight->dvDirection.u1.x;
direction[1] = lpLight->dvDirection.u2.y;
direction[2] = lpLight->dvDirection.u3.z;
direction[3] = 0.0; /* This is a directional light */
glLightfv(GL_LIGHT0 + dwLightIndex, GL_POSITION, (float *) direction);
} break;
default: WARN(" light type not handled yet...\n");
}
return DD_OK;
}
HRESULT WINAPI
GL_IDirect3DDeviceImpl_7_LightEnable(LPDIRECT3DDEVICE7 iface,
DWORD dwLightIndex,
BOOL bEnable)
{
ICOM_THIS_FROM(IDirect3DDeviceImpl, IDirect3DDevice7, iface);
TRACE("(%p/%p)->(%08lx,%d)\n", This, iface, dwLightIndex, bEnable);
if (dwLightIndex > MAX_LIGHTS) return DDERR_INVALIDPARAMS;
if (bEnable) {
if (((0x00000001 << dwLightIndex) & This->set_lights) == 0) {
/* Set the default parameters.. */
TRACE(" setting default light parameters...\n");
GL_IDirect3DDeviceImpl_7_SetLight(iface, dwLightIndex, &(This->light_parameters[dwLightIndex]));
}
glEnable(GL_LIGHT0 + dwLightIndex);
} else {
glDisable(GL_LIGHT0 + dwLightIndex);
}
return DD_OK;
}
#if !defined(__STRICT_ANSI__) && defined(__GNUC__)
# define XCAST(fun) (typeof(VTABLE_IDirect3DDevice7.fun))
#else
......@@ -1494,9 +1586,9 @@ ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
XCAST(SetViewport) Main_IDirect3DDeviceImpl_7_SetViewport,
XCAST(MultiplyTransform) Main_IDirect3DDeviceImpl_7_3T_2T_MultiplyTransform,
XCAST(GetViewport) Main_IDirect3DDeviceImpl_7_GetViewport,
XCAST(SetMaterial) Main_IDirect3DDeviceImpl_7_SetMaterial,
XCAST(SetMaterial) GL_IDirect3DDeviceImpl_7_SetMaterial,
XCAST(GetMaterial) Main_IDirect3DDeviceImpl_7_GetMaterial,
XCAST(SetLight) Main_IDirect3DDeviceImpl_7_SetLight,
XCAST(SetLight) GL_IDirect3DDeviceImpl_7_SetLight,
XCAST(GetLight) Main_IDirect3DDeviceImpl_7_GetLight,
XCAST(SetRenderState) GL_IDirect3DDeviceImpl_7_3T_2T_SetRenderState,
XCAST(GetRenderState) Main_IDirect3DDeviceImpl_7_3T_2T_GetRenderState,
......@@ -1522,7 +1614,7 @@ ICOM_VTABLE(IDirect3DDevice7) VTABLE_IDirect3DDevice7 =
XCAST(DeleteStateBlock) Main_IDirect3DDeviceImpl_7_DeleteStateBlock,
XCAST(CreateStateBlock) Main_IDirect3DDeviceImpl_7_CreateStateBlock,
XCAST(Load) Main_IDirect3DDeviceImpl_7_Load,
XCAST(LightEnable) Main_IDirect3DDeviceImpl_7_LightEnable,
XCAST(LightEnable) GL_IDirect3DDeviceImpl_7_LightEnable,
XCAST(GetLightEnable) Main_IDirect3DDeviceImpl_7_GetLightEnable,
XCAST(SetClipPlane) Main_IDirect3DDeviceImpl_7_SetClipPlane,
XCAST(GetClipPlane) Main_IDirect3DDeviceImpl_7_GetClipPlane,
......@@ -1884,6 +1976,7 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfa
int num;
XVisualInfo template;
GLenum buffer;
int light;
object = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(IDirect3DDeviceGLImpl));
if (object == NULL) return DDERR_OUTOFMEMORY;
......@@ -1965,6 +2058,29 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfa
gl_object->render_state.alpha_func = GL_ALWAYS; /* Here either but it seems logical */
gl_object->render_state.alpha_blend_enable = FALSE;
gl_object->render_state.fog_on = FALSE;
gl_object->render_state.stencil_func = GL_ALWAYS;
gl_object->render_state.stencil_mask = 0xFFFFFFFF;
gl_object->render_state.stencil_ref = 0;
gl_object->render_state.stencil_enable = FALSE;
gl_object->render_state.stencil_fail = GL_KEEP;
gl_object->render_state.stencil_zfail = GL_KEEP;
gl_object->render_state.stencil_pass = GL_KEEP;
gl_object->render_state.lighting_enable = FALSE;
gl_object->render_state.specular_enable = FALSE;
gl_object->render_state.color_diffuse = D3DMCS_COLOR1;
gl_object->render_state.color_specular = D3DMCS_COLOR2;
gl_object->render_state.color_ambient = D3DMCS_COLOR2;
gl_object->render_state.color_emissive = D3DMCS_MATERIAL;
/* Set the various light parameters */
for (light = 0; light < MAX_LIGHTS; light++) {
/* Only set the fields that are not zero-created */
object->light_parameters[light].dltType = D3DLIGHT_DIRECTIONAL;
object->light_parameters[light].dcvDiffuse.u1.r = 1.0;
object->light_parameters[light].dcvDiffuse.u2.g = 1.0;
object->light_parameters[light].dcvDiffuse.u3.b = 1.0;
object->light_parameters[light].dvDirection.u3.z = 1.0;
}
/* Allocate memory for the matrices */
object->world_mat = (D3DMATRIX *) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 16 * sizeof(float));
......
......@@ -840,7 +840,7 @@ Main_DirectDraw_GetCaps(LPDIRECTDRAW7 iface, LPDDCAPS pDriverCaps,
LPDDCAPS pHELCaps)
{
ICOM_THIS(IDirectDrawImpl,iface);
TRACE("(%p,%p,%p), stub\n",This,pDriverCaps,pHELCaps);
TRACE("(%p,%p,%p)\n",This,pDriverCaps,pHELCaps);
if (pDriverCaps != NULL) {
DD_STRUCT_COPY_BYSIZE(pDriverCaps,&This->caps);
if (TRACE_ON(ddraw)) {
......
......@@ -46,6 +46,21 @@ GLenum convert_D3D_compare_to_GL(D3DCMPFUNC dwRenderState)
return GL_ALWAYS;
}
GLenum convert_D3D_stencilop_to_GL(D3DSTENCILOP dwRenderState)
{
switch (dwRenderState) {
case D3DSTENCILOP_KEEP: return GL_KEEP;
case D3DSTENCILOP_ZERO: return GL_ZERO;
case D3DSTENCILOP_REPLACE: return GL_REPLACE;
case D3DSTENCILOP_INCRSAT: return GL_INCR;
case D3DSTENCILOP_DECRSAT: return GL_DECR;
case D3DSTENCILOP_INVERT: return GL_INVERT;
case D3DSTENCILOP_INCR: WARN("D3DSTENCILOP_INCR not properly handled !\n"); return GL_INCR;
case D3DSTENCILOP_DECR: WARN("D3DSTENCILOP_DECR not properly handled !\n"); return GL_DECR;
default: ERR("Unexpected compare type %d !\n", dwRenderState);
}
return GL_KEEP;
}
void set_render_state(D3DRENDERSTATETYPE dwRenderStateType,
DWORD dwRenderState, RenderState *rs)
......@@ -400,6 +415,47 @@ void set_render_state(D3DRENDERSTATETYPE dwRenderStateType,
case D3DRENDERSTATE_FLUSHBATCH: /* 50 */
break;
case D3DRENDERSTATE_STENCILENABLE: /* 52 */
if (dwRenderState)
glDisable(GL_STENCIL_TEST);
else
glDisable(GL_STENCIL_TEST);
break;
case D3DRENDERSTATE_STENCILFAIL: /* 53 */
rs->stencil_fail = convert_D3D_stencilop_to_GL(dwRenderState);
glStencilOp(rs->stencil_fail, rs->stencil_zfail, rs->stencil_pass);
break;
case D3DRENDERSTATE_STENCILZFAIL: /* 54 */
rs->stencil_zfail = convert_D3D_stencilop_to_GL(dwRenderState);
glStencilOp(rs->stencil_fail, rs->stencil_zfail, rs->stencil_pass);
break;
case D3DRENDERSTATE_STENCILPASS: /* 55 */
rs->stencil_pass = convert_D3D_stencilop_to_GL(dwRenderState);
glStencilOp(rs->stencil_fail, rs->stencil_zfail, rs->stencil_pass);
break;
case D3DRENDERSTATE_STENCILFUNC: /* 56 */
rs->stencil_func = convert_D3D_compare_to_GL(dwRenderState);
glStencilFunc(rs->stencil_func, rs->stencil_ref, rs->stencil_mask);
break;
case D3DRENDERSTATE_STENCILREF: /* 57 */
rs->stencil_ref = dwRenderState;
glStencilFunc(rs->stencil_func, rs->stencil_ref, rs->stencil_mask);
break;
case D3DRENDERSTATE_STENCILMASK: /* 58 */
rs->stencil_mask = dwRenderState;
glStencilFunc(rs->stencil_func, rs->stencil_ref, rs->stencil_mask);
break;
case D3DRENDERSTATE_STENCILWRITEMASK: /* 59 */
glStencilMask(dwRenderState);
break;
case D3DRENDERSTATE_LIGHTING: /* 137 */
/* There will be more to do here once we really support D3D7 Lighting.
Should be enough for now to prevent warnings :-) */
......@@ -408,6 +464,33 @@ void set_render_state(D3DRENDERSTATETYPE dwRenderStateType,
else
glDisable(GL_LIGHTING);
break;
case D3DRENDERSTATE_AMBIENT: { /* 139 */
float light[4];
light[0] = ((dwRenderState >> 16) & 0xFF) / 255.0;
light[1] = ((dwRenderState >> 8) & 0xFF) / 255.0;
light[2] = ((dwRenderState >> 0) & 0xFF) / 255.0;
light[3] = ((dwRenderState >> 24) & 0xFF) / 255.0;
glLightModelfv(GL_LIGHT_MODEL_AMBIENT, (float *) light);
} break;
case D3DRENDERSTATE_LOCALVIEWER: /* 142 */
if (dwRenderState)
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE);
else
glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, GL_FALSE);
break;
case D3DRENDERSTATE_NORMALIZENORMALS: /* 143 */
if (dwRenderState) {
glEnable(GL_NORMALIZE);
glEnable(GL_RESCALE_NORMAL);
} else {
glDisable(GL_NORMALIZE);
glDisable(GL_RESCALE_NORMAL);
}
break;
default:
ERR("Unhandled dwRenderStateType %s (%08x) !\n", _get_renderstate(dwRenderStateType), dwRenderStateType);
......
......@@ -69,6 +69,17 @@ typedef struct render_state {
GLclampf alpha_ref;
BOOLEAN alpha_blend_enable;
/* This is needed for the stencil stuff */
GLint stencil_ref;
GLuint stencil_mask;
GLenum stencil_func;
BOOLEAN stencil_enable;
GLenum stencil_fail, stencil_zfail, stencil_pass;
/* This is needed for proper lighting */
BOOLEAN lighting_enable, specular_enable;
D3DMATERIALCOLORSOURCE color_diffuse, color_specular, color_ambient, color_emissive;
/* This is needed to re-enable fogging when XYZRHW and XYZ primitives are mixed */
BOOLEAN fog_on;
} RenderState;
......@@ -175,8 +186,7 @@ extern DWORD get_flexible_vertex_size(DWORD d3dvtVertexType, DWORD *elements);
};
#define _dump_colorvalue(s,v) \
TRACE(" " s " : %f %f %f %f\n", \
(v).u1.r, (v).u2.g, (v).u3.b, (v).u4.a);
DPRINTF(" - " s); dump_D3DCOLORVALUE(&v); DPRINTF("\n");
/* This structure contains all the function pointers to OpenGL extensions
that are used by Wine */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment