nuclear@0: #ifndef _3DENGINE_H_ nuclear@0: #define _3DENGINE_H_ nuclear@0: nuclear@0: // standard includes nuclear@0: #include nuclear@0: // system includes nuclear@0: #include "d3d8.h" nuclear@0: // includes from my codebase nuclear@0: #include "typedefs.h" nuclear@0: #include "linkedlist.h" nuclear@0: #include "color.h" nuclear@0: // 3d engine includes nuclear@0: #include "n3dmath.h" nuclear@0: #include "switches.h" nuclear@0: #include "3dengtypes.h" nuclear@0: #include "material.h" nuclear@0: #include "textureman.h" nuclear@0: #include "3dgeom.h" nuclear@0: nuclear@0: enum DeviceType {DeviceHardware = D3DDEVTYPE_HAL, DeviceReference = D3DDEVTYPE_REF}; nuclear@0: enum TnLMode {HardwareTnL = D3DCREATE_HARDWARE_VERTEXPROCESSING, SoftwareTnL = D3DCREATE_SOFTWARE_VERTEXPROCESSING}; nuclear@0: enum BufferChainMode {DoubleBuffering = 1, TripleBuffering = 2}; nuclear@0: enum UsageFlags {UsageStatic = 0, UsageDynamic = D3DUSAGE_DYNAMIC}; nuclear@0: enum ShadeMode {FlatShading = D3DSHADE_FLAT, GouraudShading = D3DSHADE_GOURAUD}; nuclear@0: enum FaceOrder {Clockwise = D3DCULL_CW, CounterClockwise = D3DCULL_CCW}; nuclear@0: nuclear@0: enum PhongComponent {Ambient, Diffuse, Specular}; nuclear@0: nuclear@0: enum PrimitiveType { nuclear@0: TriangleList = D3DPT_TRIANGLELIST, nuclear@0: TriangleStrip = D3DPT_TRIANGLESTRIP, nuclear@0: TriangleFan = D3DPT_TRIANGLEFAN, nuclear@0: LineList = D3DPT_LINELIST, nuclear@0: LineStrip = D3DPT_LINESTRIP, nuclear@0: PointList = D3DPT_POINTLIST nuclear@0: }; nuclear@0: nuclear@0: enum BlendingFactor { nuclear@0: BLEND_ZERO = D3DBLEND_ZERO, nuclear@0: BLEND_ONE = D3DBLEND_ONE, nuclear@0: BLEND_SRCCOLOR = D3DBLEND_SRCCOLOR, nuclear@0: BLEND_INVSRCCOLOR = D3DBLEND_INVSRCCOLOR, nuclear@0: BLEND_SRCALPHA = D3DBLEND_SRCALPHA, nuclear@0: BLEND_INVSRCALPHA = D3DBLEND_INVSRCALPHA, nuclear@0: BLEND_DESTCOLOR = D3DBLEND_DESTCOLOR, nuclear@0: BLEND_INVDESTCOLOR = D3DBLEND_INVDESTCOLOR, nuclear@0: BLEND_DESTALPHA = D3DBLEND_DESTALPHA, nuclear@0: BLEND_INVDESTALPHA = D3DBLEND_INVDESTALPHA, nuclear@0: BLEND_SRCALPHASAT = D3DBLEND_SRCALPHASAT nuclear@0: }; nuclear@0: nuclear@0: enum CmpFunc { nuclear@0: CMP_NEVER = D3DCMP_NEVER, nuclear@0: CMP_LESS = D3DCMP_LESS, nuclear@0: CMP_EQUAL = D3DCMP_EQUAL, nuclear@0: CMP_LEQUAL = D3DCMP_LESSEQUAL, nuclear@0: CMP_GREATER = D3DCMP_GREATER, nuclear@0: CMP_NOTEQUAL = D3DCMP_NOTEQUAL, nuclear@0: CMP_GEQUAL = D3DCMP_GREATEREQUAL, nuclear@0: CMP_ALWAYS = D3DCMP_ALWAYS nuclear@0: }; nuclear@0: nuclear@0: enum StencilOp { nuclear@0: SOP_KEEP = D3DSTENCILOP_KEEP, nuclear@0: SOP_ZERO = D3DSTENCILOP_ZERO, nuclear@0: SOP_REPLACE = D3DSTENCILOP_REPLACE, nuclear@0: SOP_INCSAT = D3DSTENCILOP_INCRSAT, nuclear@0: SOP_DECSAT = D3DSTENCILOP_DECRSAT, nuclear@0: SOP_INVERT = D3DSTENCILOP_INVERT, nuclear@0: SOP_INC = D3DSTENCILOP_INCR, nuclear@0: SOP_DEC = D3DSTENCILOP_DECR nuclear@0: }; nuclear@0: nuclear@0: enum TextureBlendFunction { nuclear@0: TexBlendSelectArg1 = D3DTOP_SELECTARG1, // S[rgba] = Arg1 nuclear@0: TexBlendSelectArg2 = D3DTOP_SELECTARG2, // S[rgba] = Arg2 nuclear@0: TexBlendAdd = D3DTOP_ADD, // S[rgba] = Arg1 + Arg2 nuclear@0: TexBlendAddSigned = D3DTOP_ADDSIGNED, // S[rgba] = Arg1 + Arg2 - 0.5 nuclear@0: TexBlendAddSigned2x = D3DTOP_ADDSIGNED2X, // S[rgba] = (Arg1 + Arg2 - 0.5) << 1 nuclear@0: TexBlendSubtract = D3DTOP_SUBTRACT, // S[rgba] = Arg1 - Arg2 nuclear@0: TexBlendAddSmooth = D3DTOP_ADDSMOOTH, // S[rgba] = (Arg1 + Arg2) - (Arg1 * Arg2) nuclear@0: TexBlendModulate = D3DTOP_MODULATE, // S[rgba] = Arg1 * Arg2 nuclear@0: TexBlendModulate2x = D3DTOP_MODULATE2X, // S[rgba] = (Arg1 * Arg2) << 1 nuclear@0: TexBlendModulate4x = D3DTOP_MODULATE4X, // S[rgba] = (Arg1 * Arg2) << 2 nuclear@0: TexBlendVertexAlpha = D3DTOP_BLENDDIFFUSEALPHA, // S[rgba] = Arg1*Alpha + Arg2*(1-Alpha) nuclear@0: TexBlendTextureAlpha = D3DTOP_BLENDTEXTUREALPHA, // S[rgba] = Arg1*Alpha + Arg2*(1-Alpha) nuclear@0: TexBlendFactorAlpha = D3DTOP_BLENDFACTORALPHA, // S[rgba] = Arg1*Alpha + Arg2*(1-Alpha) nuclear@0: TexBlendPrevAlpha = D3DTOP_BLENDFACTORALPHA, // S[rgba] = Arg1*Alpha + Arg2*(1-Alpha) nuclear@0: TexBlendPreMulAlpha = D3DTOP_BLENDTEXTUREALPHAPM, // S[rgba] = Arg1 + Arg2*(1-Alpha) nuclear@0: TexBlendPreModulate = D3DTOP_PREMODULATE, nuclear@0: TexBlendModAlphaAddColor = D3DTOP_MODULATEALPHA_ADDCOLOR,// S[rgba] = Arg1[rgb] + Arg1[a] * Arg2[rgb] nuclear@0: TexBlendModulateAddAlpha = D3DTOP_MODULATECOLOR_ADDALPHA,// S[rgba] = Arg1[rgb] * Arg2[rgb] + Arg1[a] nuclear@0: TexBlendModInvAlphaAddColor = D3DTOP_MODULATEINVALPHA_ADDCOLOR, // S[rgba] = Arg1[rgb] + (1-Arg1[a]) * Arg2[rgb] nuclear@0: TexBlendModulateInvAddAlpha = D3DTOP_MODULATEINVCOLOR_ADDALPHA, // S[rgba] = (1-Arg1[rgb]) * Arg2[rgb] + Arg1[a] nuclear@0: TexBlendBumpEnv = D3DTOP_BUMPENVMAP, // bump mapping with next stage's env map nuclear@0: TexBlendBumpEnvLuminance = D3DTOP_BUMPENVMAPLUMINANCE, // bump mapping with next stage's env map with luminance nuclear@0: TexBlendDotProduct = D3DTOP_DOTPRODUCT3, // S[rgba] = Arg1[rgb] (dot) Arg2[rgb] nuclear@0: TexBlendMultiplyAdd = D3DTOP_MULTIPLYADD, // S[rgba] = Arg1 + Arg2 * Arg3 nuclear@0: TexBlendLerp = D3DTOP_LERP // S[rgba] = Arg2 + (Arg3 - Arg2) * Arg1 nuclear@0: }; nuclear@0: nuclear@0: enum TextureBlendArgument { nuclear@0: TexArgNone = 0, // valid only for arg3 nuclear@0: TexArgCurrent = D3DTA_CURRENT, // the color from the previous stage output (diffuse for 1st) nuclear@0: TexArgDiffuseColor = D3DTA_DIFFUSE, // the diffuse interpolated color nuclear@0: TexArgSpecularColor = D3DTA_SPECULAR, // the specular interpolated color nuclear@0: TexArgTexture = D3DTA_TEXTURE, // the texture bound to this stage nuclear@0: TexArgFactor = D3DTA_TFACTOR, // a user defined factor nuclear@0: TexArgTemp = D3DTA_TEMP // temp register nuclear@0: }; nuclear@0: nuclear@0: enum TextureFilteringType { nuclear@0: PointSampling, nuclear@0: BilinearFiltering, nuclear@0: TrilinearFiltering, nuclear@0: AnisotropicFiltering nuclear@0: }; nuclear@0: nuclear@0: enum TextureAddressing { nuclear@0: TexAddrWrap = D3DTADDRESS_WRAP, nuclear@0: TexAddrMirror = D3DTADDRESS_MIRROR, nuclear@0: TexAddrClamp = D3DTADDRESS_CLAMP, nuclear@0: TexAddrBorder = D3DTADDRESS_BORDER, nuclear@0: TexAddrMirrorOnce = D3DTADDRESS_MIRRORONCE nuclear@0: }; nuclear@0: nuclear@0: enum TexTransformState { nuclear@0: TexTransformDisable = D3DTTFF_DISABLE, nuclear@0: TexTransform1D = D3DTTFF_COUNT1, nuclear@0: TexTransform2D = D3DTTFF_COUNT2, nuclear@0: TexTransform3D = D3DTTFF_COUNT3, nuclear@0: TexTransform4D = D3DTTFF_COUNT4, nuclear@0: TexTransformProjected = D3DTTFF_PROJECTED nuclear@0: }; nuclear@0: nuclear@0: // don't care flags for context creation nuclear@0: const unsigned short GCPDONTCARE_NONE = 0; // 0000000000000000 nuclear@0: const unsigned short GCPDONTCARE_BPP = 1; // 0000000000000001 nuclear@0: const unsigned short GCPDONTCARE_REFRESH = 2; // 0000000000000010 nuclear@0: const unsigned short GCPDONTCARE_ALPHA = 4; // 0000000000000100 nuclear@0: const unsigned short GCPDONTCARE_DEPTH = 8; // 0000000000001000 nuclear@0: const unsigned short GCPDONTCARE_TNL = 16; // 0000000000010000 nuclear@0: const unsigned short GCPDONTCARE_BUFFERS = 32; // 0000000000100000 nuclear@0: const unsigned short GCPDONTCARE_AA = 64; // 0000000001000000 nuclear@0: const unsigned short GCPDONTCARE_VSYNC = 128; // 0000000010000000 nuclear@0: nuclear@0: // fullscreen / windowed flags nuclear@0: const unsigned short GCCREATE_WINDOWED = 0; nuclear@0: const unsigned short GCCREATE_FULLSCREEN = 1; nuclear@0: nuclear@0: nuclear@0: nuclear@0: class Vertex; nuclear@0: nuclear@0: struct ColorDepth { nuclear@0: int bpp, colorbits, alpha; nuclear@0: nuclear@0: ColorDepth(int bits=0, int c=0, int a=0) {colorbits = c; alpha = a; bpp = bits; } nuclear@0: }; nuclear@0: nuclear@0: struct DisplayMode { nuclear@0: unsigned int XRes, YRes, RefreshRate; nuclear@0: ColorDepth ColorFormat; nuclear@0: }; nuclear@0: nuclear@0: enum DisplayModeItem {ModeItemSize, ModeItemBpp, ModeItemAlpha, ModeItemRefresh}; nuclear@0: nuclear@0: struct Adapter { nuclear@0: char *Driver, *Description; nuclear@0: int64 DriverVersion; nuclear@0: dword VentorID, DeviceID, SubSysID, Revision; nuclear@0: GUID DeviceGUID; nuclear@0: nuclear@0: unsigned int ModeCount; nuclear@0: DisplayMode *Modes; nuclear@0: D3DCAPS8 Capabilities; nuclear@0: }; nuclear@0: nuclear@0: struct RenderTarget { nuclear@0: Surface *ColorSurface, *DepthStencilSurface; nuclear@0: }; nuclear@0: nuclear@0: struct RenderParams { nuclear@0: ShadeMode Shading; nuclear@0: bool Billboarded; nuclear@0: dword VertexProgram; nuclear@0: dword PixelProgram; nuclear@0: bool ZWrite; nuclear@0: BlendingFactor SourceBlendFactor, DestBlendFactor; nuclear@0: }; nuclear@0: nuclear@0: struct ContextInitParameters { nuclear@0: int x, y; nuclear@0: int bpp; nuclear@0: int RefreshRate; nuclear@0: bool AlphaChannel; nuclear@0: int DepthBits; nuclear@0: DeviceType DevType; nuclear@0: bool HardwareTnL; nuclear@0: bool FullScreen; nuclear@0: bool Antialiasing; nuclear@0: bool BestAA; nuclear@0: bool VSync; nuclear@0: BufferChainMode Buffers; nuclear@0: unsigned short DontCareFlags; nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: class GraphicsContext { nuclear@0: private: nuclear@0: PrimitiveType ptype; nuclear@0: FaceOrder CullOrder; nuclear@0: bool BackfaceCulling; nuclear@0: bool MipMapEnabled; nuclear@0: bool BillBoardingEnabled; nuclear@0: dword MipFilter; nuclear@0: nuclear@0: // cache of current transformation matrices nuclear@0: Matrix4x4 WorldMat[256], ViewMat, ProjMat, TexMat[8]; nuclear@0: nuclear@0: // disable copying contexts by making copy constructor and assignment private nuclear@0: GraphicsContext(const GraphicsContext &gc); nuclear@0: const GraphicsContext &operator =(const GraphicsContext &gc); nuclear@0: nuclear@0: public: nuclear@0: HWND WindowHandle; nuclear@0: RenderTarget MainRenderTarget; nuclear@0: IDirect3DDevice8 *D3DDevice; nuclear@0: ContextInitParameters ContextParams; nuclear@0: D3DFORMAT ColorFormat, ZFormat; nuclear@0: int AASamples; nuclear@0: int MaxTextureStages; nuclear@0: nuclear@0: TextureManager *texman; // texture manager nuclear@0: nuclear@0: GraphicsContext(); nuclear@0: nuclear@0: void SetDefaultStates(); nuclear@0: nuclear@0: bool CreateVertexBuffer(uint32 VertexCount, UsageFlags usage, VertexBuffer **vb) const; nuclear@0: bool CreateIndexBuffer(uint32 IndexCount, UsageFlags usage, IndexBuffer **ib) const; nuclear@0: nuclear@0: bool CreateSurface(uint32 Width, uint32 Height, Surface **surf) const; nuclear@0: bool CreateDepthStencil(uint32 Width, uint32 Height, Surface **zsurf) const; nuclear@0: nuclear@0: void Clear(dword color) const; nuclear@0: void ClearZBuffer(float zval) const; nuclear@0: void ClearStencil(byte sval) const; nuclear@0: void ClearZBufferStencil(float zval, byte sval) const; nuclear@0: nuclear@0: void Flip() const; nuclear@0: nuclear@0: bool Draw(VertexBuffer *vb); nuclear@0: bool Draw(Vertex *varray, unsigned int VertexCount); nuclear@0: bool Draw(VertexBuffer *vb, IndexBuffer *ib); nuclear@0: bool Draw(Vertex *varray, Index *iarray, unsigned int VertexCount, unsigned int IndexCount); nuclear@0: bool Draw(Vertex *varray, Triangle *triarray, unsigned int VertexCount, unsigned int TriCount); nuclear@0: nuclear@0: IDirect3DDevice8 *GetDevice() const; nuclear@0: int GetTextureStageNumber() const {return MaxTextureStages;} nuclear@0: nuclear@0: ////// render states ////// nuclear@0: void SetPrimitiveType(PrimitiveType pt); nuclear@0: void SetBackfaceCulling(bool enable); nuclear@0: void SetFrontFace(FaceOrder order); nuclear@0: void SetAutoNormalize(bool enable); nuclear@0: void SetBillboarding(bool enable); nuclear@0: void SetColorWrite(bool red, bool green, bool blue, bool alpha); nuclear@0: nuclear@0: // blending states nuclear@0: void SetAlphaBlending(bool enable); nuclear@0: void SetBlendFunc(BlendingFactor src, BlendingFactor dest); nuclear@0: nuclear@0: // zbuffer states nuclear@0: void SetZBuffering(bool enable); nuclear@0: void SetZWrite(bool enable); nuclear@0: void SetZFunc(CmpFunc func); nuclear@0: nuclear@0: // set stencil buffer states nuclear@0: void SetStencilBuffering(bool enable); nuclear@0: void SetStencilPassOp(StencilOp sop); nuclear@0: void SetStencilFailOp(StencilOp sop); nuclear@0: void SetStencilPassZFailOp(StencilOp sop); nuclear@0: void SetStencilOp(StencilOp Fail, StencilOp StencilPassZFail, StencilOp Pass); nuclear@0: void SetStencilFunc(CmpFunc func); nuclear@0: void SetStencilReference(dword value); nuclear@0: nuclear@0: // texture & material states nuclear@0: void SetTextureFiltering(TextureFilteringType texfilter, int TextureStage = 0xa11); nuclear@0: void SetTextureAddressing(TextureAddressing uaddr, TextureAddressing vaddr, int TextureStage = 0xa11); nuclear@0: void SetTextureBorderColor(dword color, int TextureStage = 0xa11); nuclear@0: void SetTexture(int index, Texture *tex); nuclear@0: void SetTextureFactor(dword factor); nuclear@0: void SetMipMapping(bool enable, int TextureStage = 0xa11); nuclear@0: void SetMaterial(const Material &mat); nuclear@0: nuclear@0: void BlitTexture(const Texture *texture, RECT *rect, const Color &col = Color(1.0f)); nuclear@0: nuclear@0: // multitexturing interface nuclear@0: void EnableTextureStage(int stage); nuclear@0: void DisableTextureStage(int stage); nuclear@0: void SetTextureStageColor(int stage, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3 = TexArgNone); nuclear@0: void SetTextureStageAlpha(int stage, TextureBlendFunction op, TextureBlendArgument arg1, TextureBlendArgument arg2, TextureBlendArgument arg3 = TexArgNone); nuclear@0: void SetTextureCoordIndex(int stage, int index); nuclear@0: void SetTextureTransformState(int stage, TexTransformState TexXForm); nuclear@0: //void SetTextureCoordGenerator(int stage, TexGen tgen); nuclear@0: nuclear@0: // programmable interface nuclear@0: void SetVertexProgram(dword vs); nuclear@0: void SetPixelProgram(dword ps); nuclear@0: nuclear@0: dword CreateVertexProgram(const char *fname); nuclear@0: void DestroyVertexProgram(dword vprog); nuclear@0: void SetVertexProgramConstant(dword creg, float val); nuclear@0: void SetVertexProgramConstant(dword creg, const Vector3 &val); nuclear@0: void SetVertexProgramConstant(dword creg, const Vector4 &val); nuclear@0: void SetVertexProgramConstant(dword creg, const Color &val); nuclear@0: void SetVertexProgramConstant(dword creg, const Matrix4x4 &val); nuclear@0: void SetVertexProgramConstant(dword creg, const void *data, dword size); nuclear@0: nuclear@0: nuclear@0: // lighting states nuclear@0: void SetLighting(bool enable); nuclear@0: void SetColorVertex(bool enable); nuclear@0: void SetAmbientLight(Color AmbientColor); nuclear@0: void SetShadingMode(ShadeMode mode); nuclear@0: void SetSpecular(bool enable); nuclear@0: nuclear@0: // Transformation Matrices nuclear@0: void SetWorldMatrix(const Matrix4x4 &WorldMat, unsigned int BlendIndex = 0); nuclear@0: void SetViewMatrix(const Matrix4x4 &ViewMat); nuclear@0: void SetProjectionMatrix(const Matrix4x4 &ProjMat); nuclear@0: void SetTextureMatrix(const Matrix4x4 &TexMat, unsigned int TextureStage = 0); nuclear@0: void SetViewport(unsigned int x, unsigned int y, unsigned int xsize, unsigned int ysize, float MinZ = 0.0f, float MaxZ = 1.0f); nuclear@0: nuclear@0: const Matrix4x4 &GetWorldMatrix(unsigned int BlendIndex = 0); nuclear@0: const Matrix4x4 &GetViewMatrix(); nuclear@0: const Matrix4x4 &GetProjectionMatrix(); nuclear@0: const Matrix4x4 &GetTextureMatrix(unsigned int TextureStage = 0); nuclear@0: nuclear@0: // render target nuclear@0: void ResetRenderTarget(); nuclear@0: void SetRenderTarget(RenderTarget &rtarg); nuclear@0: void SetRenderTarget(Texture *rtarg, Texture *ztarg); nuclear@0: void SetRenderTarget(Texture *rtarg, Surface *ztarg); nuclear@0: //RenderTarget GetRenderTarget() const; nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: nuclear@0: class Engine3D { nuclear@0: private: nuclear@0: IDirect3D8 *d3d; nuclear@0: unsigned int AdapterCount; nuclear@0: Adapter *adapters; // array of adapters (filled in at the constructor) nuclear@0: std::vector GraphicsContexts; // a list of active graphics contexts nuclear@0: nuclear@0: void RetrieveAdapterInfo(); nuclear@0: LinkedList *CreateModesList(unsigned int AdapterID) const; nuclear@0: void NarrowModesList(LinkedList *list, DisplayModeItem item, long value, long value2=0) const; nuclear@0: DisplayMode ChooseBestMode(LinkedList *modes) const; nuclear@0: int MaxAntialiasingSamples() const; nuclear@0: nuclear@0: public: nuclear@0: nuclear@0: Engine3D(); nuclear@0: ~Engine3D(); nuclear@0: nuclear@0: int GetAdapterCount() const; nuclear@0: const Adapter *GetAdapterInfo(int adapter) const; nuclear@0: nuclear@0: GraphicsContext *CreateGraphicsContext(HWND WindowHandle, int x, int y, int bpp, word flags); nuclear@0: GraphicsContext *CreateGraphicsContext(HWND WindowHandle, unsigned int AdapterID, ContextInitParameters *GCParams); nuclear@0: ContextInitParameters LoadContextParamsConfigFile(const char *cfgfilename); nuclear@0: nuclear@0: void DestroyGraphicsContext(GraphicsContext *gc); nuclear@0: }; nuclear@0: nuclear@0: class Light; nuclear@0: nuclear@0: // helper functions nuclear@0: bool Lock(VertexBuffer *vb, Vertex **data); nuclear@0: bool Lock(IndexBuffer *ib, Index **data); nuclear@0: void Unlock(VertexBuffer *vb); nuclear@0: void Unlock(IndexBuffer *ib); nuclear@0: void CreateProjectionMatrix(Matrix4x4 *mat, float yFOV, float Aspect, float NearClip, float FarClip); nuclear@0: void NormalMapFromHeightField(Texture *tex); nuclear@0: void UpdateMipmapChain(Texture *tex); nuclear@0: TriMesh *CreateShadowVolume(const TriMesh &mesh, const Light *light, const Matrix4x4 &MeshXForm, bool WorldCoords = false); nuclear@0: nuclear@0: #endif // _3DENGINE_H_