Drop support for the DirectX9 renderer
This commit is contained in:
parent
65ee612110
commit
c11a7236c7
@ -190,19 +190,6 @@ source/Irrlicht/Irrlicht.cpp
|
||||
source/Irrlicht/irrXML.cpp
|
||||
source/Irrlicht/os.cpp
|
||||
source/Irrlicht/COpenGLNormalMapRenderer.cpp
|
||||
source/Irrlicht/CD3D9Driver.cpp
|
||||
source/Irrlicht/CD3D9Driver.h
|
||||
source/Irrlicht/CD3D9HLSLMaterialRenderer.cpp
|
||||
source/Irrlicht/CD3D9HLSLMaterialRenderer.h
|
||||
source/Irrlicht/CD3D9MaterialRenderer.h
|
||||
source/Irrlicht/CD3D9NormalMapRenderer.cpp
|
||||
source/Irrlicht/CD3D9NormalMapRenderer.h
|
||||
source/Irrlicht/CD3D9ParallaxMapRenderer.cpp
|
||||
source/Irrlicht/CD3D9ParallaxMapRenderer.h
|
||||
source/Irrlicht/CD3D9ShaderMaterialRenderer.cpp
|
||||
source/Irrlicht/CD3D9ShaderMaterialRenderer.h
|
||||
source/Irrlicht/CD3D9Texture.cpp
|
||||
source/Irrlicht/CD3D9Texture.h
|
||||
source/Irrlicht/CAnimatedMeshSceneNode.h
|
||||
source/Irrlicht/CAttributeImpl.h
|
||||
source/Irrlicht/CAttributes.h
|
||||
|
@ -12,3 +12,6 @@ The following changes have been made:
|
||||
- non-triangle VBO support
|
||||
- extension order mismatch
|
||||
- support for some RG texture formats
|
||||
|
||||
Changes in 12/2023:
|
||||
- drop DirectX9-related code
|
File diff suppressed because it is too large
Load Diff
@ -1,499 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
#define __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#ifdef _IRR_WINDOWS_
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "CNullDriver.h"
|
||||
#include "SIrrCreationParameters.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
#include "Cg/cg.h"
|
||||
#include "Cg/cgD3D9.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
struct SDepthSurface : public IReferenceCounted
|
||||
{
|
||||
SDepthSurface() : Surface(0)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("SDepthSurface");
|
||||
#endif
|
||||
}
|
||||
virtual ~SDepthSurface()
|
||||
{
|
||||
if (Surface)
|
||||
Surface->Release();
|
||||
}
|
||||
|
||||
IDirect3DSurface9* Surface;
|
||||
core::dimension2du Size;
|
||||
};
|
||||
|
||||
class CD3D9Driver : public CNullDriver, IMaterialRendererServices
|
||||
{
|
||||
public:
|
||||
|
||||
friend class CD3D9Texture;
|
||||
|
||||
//! constructor
|
||||
CD3D9Driver(const SIrrlichtCreationParameters& params, io::IFileSystem* io);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D9Driver();
|
||||
|
||||
//! applications must call this method before performing any rendering. returns false if failed.
|
||||
virtual bool beginScene(bool backBuffer=true, bool zBuffer=true,
|
||||
SColor color=SColor(255,0,0,0),
|
||||
const SExposedVideoData& videoData=SExposedVideoData(),
|
||||
core::rect<s32>* sourceRect=0);
|
||||
|
||||
//! applications must call this method after performing any rendering. returns false if failed.
|
||||
virtual bool endScene();
|
||||
|
||||
//! queries the features of the driver, returns true if feature is available
|
||||
virtual bool queryFeature(E_VIDEO_DRIVER_FEATURE feature) const;
|
||||
|
||||
//! sets transformation
|
||||
virtual void setTransform(E_TRANSFORMATION_STATE state, const core::matrix4& mat);
|
||||
|
||||
//! sets a material
|
||||
virtual void setMaterial(const SMaterial& material);
|
||||
|
||||
//! sets a render target
|
||||
virtual bool setRenderTarget(video::ITexture* texture,
|
||||
bool clearBackBuffer=true, bool clearZBuffer=true,
|
||||
SColor color=video::SColor(0,0,0,0));
|
||||
|
||||
//! Sets multiple render targets
|
||||
virtual bool setRenderTarget(const core::array<video::IRenderTarget>& texture,
|
||||
bool clearBackBuffer=true, bool clearZBuffer=true,
|
||||
SColor color=video::SColor(0,0,0,0));
|
||||
|
||||
//! sets a viewport
|
||||
virtual void setViewPort(const core::rect<s32>& area);
|
||||
|
||||
//! gets the area of the current viewport
|
||||
virtual const core::rect<s32>& getViewPort() const;
|
||||
|
||||
struct SHWBufferLink_d3d9 : public SHWBufferLink
|
||||
{
|
||||
SHWBufferLink_d3d9(const scene::IMeshBuffer *_MeshBuffer):
|
||||
SHWBufferLink(_MeshBuffer),
|
||||
vertexBuffer(0), indexBuffer(0),
|
||||
vertexBufferSize(0), indexBufferSize(0) {}
|
||||
|
||||
IDirect3DVertexBuffer9* vertexBuffer;
|
||||
IDirect3DIndexBuffer9* indexBuffer;
|
||||
|
||||
u32 vertexBufferSize;
|
||||
u32 indexBufferSize;
|
||||
};
|
||||
|
||||
bool updateVertexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
|
||||
bool updateIndexHardwareBuffer(SHWBufferLink_d3d9 *HWBuffer);
|
||||
|
||||
//! updates hardware buffer if needed
|
||||
virtual bool updateHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Create hardware buffer from mesh
|
||||
virtual SHWBufferLink *createHardwareBuffer(const scene::IMeshBuffer* mb);
|
||||
|
||||
//! Delete hardware buffer (only some drivers can)
|
||||
virtual void deleteHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Draw hardware buffer
|
||||
virtual void drawHardwareBuffer(SHWBufferLink *HWBuffer);
|
||||
|
||||
//! Create occlusion query.
|
||||
/** Use node for identification and mesh for occlusion test. */
|
||||
virtual void addOcclusionQuery(scene::ISceneNode* node,
|
||||
const scene::IMesh* mesh=0);
|
||||
|
||||
//! Remove occlusion query.
|
||||
virtual void removeOcclusionQuery(scene::ISceneNode* node);
|
||||
|
||||
//! Run occlusion query. Draws mesh stored in query.
|
||||
/** If the mesh shall not be rendered visible, use
|
||||
overrideMaterial to disable the color and depth buffer. */
|
||||
virtual void runOcclusionQuery(scene::ISceneNode* node, bool visible=false);
|
||||
|
||||
//! Update occlusion query. Retrieves results from GPU.
|
||||
/** If the query shall not block, set the flag to false.
|
||||
Update might not occur in this case, though */
|
||||
virtual void updateOcclusionQuery(scene::ISceneNode* node, bool block=true);
|
||||
|
||||
//! Return query result.
|
||||
/** Return value is the number of visible pixels/fragments.
|
||||
The value is a safe approximation, i.e. can be larger then the
|
||||
actual value of pixels. */
|
||||
virtual u32 getOcclusionQueryResult(scene::ISceneNode* node) const;
|
||||
|
||||
//! draws a vertex primitive list
|
||||
virtual void drawVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType);
|
||||
|
||||
//! draws a vertex primitive list in 2d
|
||||
virtual void draw2DVertexPrimitiveList(const void* vertices, u32 vertexCount,
|
||||
const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType);
|
||||
|
||||
//! draws an 2d image, using a color (if color is other then Color(255,255,255,255)) and the alpha channel of the texture if wanted.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::position2d<s32>& destPos,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
SColor color=SColor(255,255,255,255), bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//! Draws a part of the texture into the rectangle.
|
||||
virtual void draw2DImage(const video::ITexture* texture, const core::rect<s32>& destRect,
|
||||
const core::rect<s32>& sourceRect, const core::rect<s32>* clipRect = 0,
|
||||
const video::SColor* const colors=0, bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//! Draws a set of 2d images, using a color and the alpha channel of the texture.
|
||||
virtual void draw2DImageBatch(const video::ITexture* texture,
|
||||
const core::array<core::position2d<s32> >& positions,
|
||||
const core::array<core::rect<s32> >& sourceRects,
|
||||
const core::rect<s32>* clipRect=0,
|
||||
SColor color=SColor(255,255,255,255),
|
||||
bool useAlphaChannelOfTexture=false);
|
||||
|
||||
//!Draws an 2d rectangle with a gradient.
|
||||
virtual void draw2DRectangle(const core::rect<s32>& pos,
|
||||
SColor colorLeftUp, SColor colorRightUp, SColor colorLeftDown, SColor colorRightDown,
|
||||
const core::rect<s32>* clip);
|
||||
|
||||
//! Draws a 2d line.
|
||||
virtual void draw2DLine(const core::position2d<s32>& start,
|
||||
const core::position2d<s32>& end,
|
||||
SColor color=SColor(255,255,255,255));
|
||||
|
||||
//! Draws a pixel.
|
||||
virtual void drawPixel(u32 x, u32 y, const SColor & color);
|
||||
|
||||
//! Draws a 3d line.
|
||||
virtual void draw3DLine(const core::vector3df& start,
|
||||
const core::vector3df& end, SColor color = SColor(255,255,255,255));
|
||||
|
||||
//! initialises the Direct3D API
|
||||
bool initDriver(HWND hwnd, bool pureSoftware);
|
||||
|
||||
//! \return Returns the name of the video driver. Example: In case of the DIRECT3D8
|
||||
//! driver, it would return "Direct3D8.1".
|
||||
virtual const wchar_t* getName() const;
|
||||
|
||||
//! deletes all dynamic lights there are
|
||||
virtual void deleteAllDynamicLights();
|
||||
|
||||
//! adds a dynamic light, returning an index to the light
|
||||
//! \param light: the light data to use to create the light
|
||||
//! \return An index to the light, or -1 if an error occurs
|
||||
virtual s32 addDynamicLight(const SLight& light);
|
||||
|
||||
//! Turns a dynamic light on or off
|
||||
//! \param lightIndex: the index returned by addDynamicLight
|
||||
//! \param turnOn: true to turn the light on, false to turn it off
|
||||
virtual void turnLightOn(s32 lightIndex, bool turnOn);
|
||||
|
||||
//! returns the maximal amount of dynamic lights the device can handle
|
||||
virtual u32 getMaximalDynamicLightAmount() const;
|
||||
|
||||
//! Sets the dynamic ambient light color. The default color is
|
||||
//! (0,0,0,0) which means it is dark.
|
||||
//! \param color: New color of the ambient light.
|
||||
virtual void setAmbientLight(const SColorf& color);
|
||||
|
||||
//! Draws a shadow volume into the stencil buffer.
|
||||
virtual void drawStencilShadowVolume(const core::array<core::vector3df>& triangles, bool zfail=true, u32 debugDataVisible=0);
|
||||
|
||||
//! Fills the stencil shadow with color.
|
||||
virtual void drawStencilShadow(bool clearStencilBuffer=false,
|
||||
video::SColor leftUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightUpEdge = video::SColor(0,0,0,0),
|
||||
video::SColor leftDownEdge = video::SColor(0,0,0,0),
|
||||
video::SColor rightDownEdge = video::SColor(0,0,0,0));
|
||||
|
||||
//! Returns the maximum amount of primitives (mostly vertices) which
|
||||
//! the device is able to render with one drawIndexedTriangleList
|
||||
//! call.
|
||||
virtual u32 getMaximalPrimitiveCount() const;
|
||||
|
||||
//! Enables or disables a texture creation flag.
|
||||
virtual void setTextureCreationFlag(E_TEXTURE_CREATION_FLAG flag, bool enabled);
|
||||
|
||||
//! Sets the fog mode.
|
||||
virtual void setFog(SColor color, E_FOG_TYPE fogType, f32 start,
|
||||
f32 end, f32 density, bool pixelFog, bool rangeFog);
|
||||
|
||||
//! Only used by the internal engine. Used to notify the driver that
|
||||
//! the window was resized.
|
||||
virtual void OnResize(const core::dimension2d<u32>& size);
|
||||
|
||||
//! Can be called by an IMaterialRenderer to make its work easier.
|
||||
virtual void setBasicRenderStates(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates);
|
||||
|
||||
//! Returns type of video driver
|
||||
virtual E_DRIVER_TYPE getDriverType() const;
|
||||
|
||||
//! Returns the transformation set by setTransform
|
||||
virtual const core::matrix4& getTransform(E_TRANSFORMATION_STATE state) const;
|
||||
|
||||
//! Sets a vertex shader constant.
|
||||
virtual void setVertexShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
|
||||
//! Sets a pixel shader constant.
|
||||
virtual void setPixelShaderConstant(const f32* data, s32 startRegister, s32 constantAmount=1);
|
||||
|
||||
//! Sets a constant for the vertex shader based on a name.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVertexShaderConstant(const c8* name, const s32* ints, int count);
|
||||
|
||||
//! Sets a constant for the pixel shader based on a name.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setPixelShaderConstant(const c8* name, const s32* ints, int count);
|
||||
|
||||
//! Returns a pointer to the IVideoDriver interface. (Implementation for
|
||||
//! IMaterialRendererServices)
|
||||
virtual IVideoDriver* getVideoDriver();
|
||||
|
||||
//! Creates a render target texture.
|
||||
virtual ITexture* addRenderTargetTexture(const core::dimension2d<u32>& size,
|
||||
const io::path& name, const ECOLOR_FORMAT format = ECF_UNKNOWN, const bool useStencil = false);
|
||||
|
||||
//! Clears the ZBuffer.
|
||||
virtual void clearZBuffer();
|
||||
|
||||
//! Returns an image created from the last rendered frame.
|
||||
virtual IImage* createScreenShot(video::ECOLOR_FORMAT format=video::ECF_UNKNOWN, video::E_RENDER_TARGET target=video::ERT_FRAME_BUFFER);
|
||||
|
||||
//! Set/unset a clipping plane.
|
||||
virtual bool setClipPlane(u32 index, const core::plane3df& plane, bool enable=false);
|
||||
|
||||
//! Enable/disable a clipping plane.
|
||||
virtual void enableClipPlane(u32 index, bool enable);
|
||||
|
||||
//! Returns the graphics card vendor name.
|
||||
virtual core::stringc getVendorInfo() {return VendorName;}
|
||||
|
||||
//! Enable the 2d override material
|
||||
virtual void enableMaterial2D(bool enable=true);
|
||||
|
||||
//! Check if the driver was recently reset.
|
||||
virtual bool checkDriverReset() {return DriverWasReset;}
|
||||
|
||||
// removes the depth struct from the DepthSurface array
|
||||
void removeDepthSurface(SDepthSurface* depth);
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer. */
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! Returns the maximum texture size supported.
|
||||
virtual core::dimension2du getMaxTextureSize() const;
|
||||
|
||||
//! Get the current color format of the color buffer
|
||||
/** \return Color format of the color buffer as D3D color value. */
|
||||
D3DFORMAT getD3DColorFormat() const;
|
||||
|
||||
//! Get D3D color format from Irrlicht color format.
|
||||
D3DFORMAT getD3DFormatFromColorFormat(ECOLOR_FORMAT format) const;
|
||||
|
||||
//! Get Irrlicht color format from D3D color format.
|
||||
ECOLOR_FORMAT getColorFormatFromD3DFormat(D3DFORMAT format) const;
|
||||
|
||||
//! Get Cg context
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
const CGcontext& getCgContext();
|
||||
#endif
|
||||
|
||||
virtual void enableScissorTest(const core::rect<s32>& r);
|
||||
virtual void disableScissorTest();
|
||||
|
||||
private:
|
||||
|
||||
//! enumeration for rendering modes such as 2d and 3d for minizing the switching of renderStates.
|
||||
enum E_RENDER_MODE
|
||||
{
|
||||
ERM_NONE = 0, // no render state has been set yet.
|
||||
ERM_2D, // 2d drawing rendermode
|
||||
ERM_3D, // 3d rendering mode
|
||||
ERM_STENCIL_FILL, // stencil fill mode
|
||||
ERM_SHADOW_VOLUME_ZFAIL, // stencil volume draw mode
|
||||
ERM_SHADOW_VOLUME_ZPASS // stencil volume draw mode
|
||||
};
|
||||
|
||||
//! sets right vertex shader
|
||||
void setVertexShader(video::E_VERTEX_TYPE newType);
|
||||
|
||||
//! sets the needed renderstates
|
||||
bool setRenderStates3DMode();
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStates2DMode(bool alpha, bool texture, bool alphaChannel);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilFillMode(bool alpha);
|
||||
|
||||
//! sets the needed renderstates
|
||||
void setRenderStatesStencilShadowMode(bool zfail, u32 debugDataVisible);
|
||||
|
||||
//! sets the current Texture
|
||||
bool setActiveTexture(u32 stage, const video::ITexture* texture);
|
||||
|
||||
//! resets the device
|
||||
bool reset();
|
||||
|
||||
//! returns a device dependent texture from a software surface (IImage)
|
||||
//! THIS METHOD HAS TO BE OVERRIDDEN BY DERIVED DRIVERS WITH OWN TEXTURES
|
||||
virtual video::ITexture* createDeviceDependentTexture(IImage* surface, const io::path& name, void* mipmapData=0);
|
||||
|
||||
//! returns the current size of the screen or rendertarget
|
||||
virtual const core::dimension2d<u32>& getCurrentRenderTargetSize() const;
|
||||
|
||||
//! Check if a proper depth buffer for the RTT is available, otherwise create it.
|
||||
void checkDepthBuffer(ITexture* tex);
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, using pixel and/or
|
||||
//! vertex shaders to render geometry.
|
||||
s32 addShaderMaterial(const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
E_MATERIAL_TYPE baseMaterial, s32 userData);
|
||||
|
||||
//! Adds a new material renderer to the VideoDriver, based on a high level shading
|
||||
//! language.
|
||||
virtual s32 addHighLevelShaderMaterial(
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
const c8* geometryShaderProgram,
|
||||
const c8* geometryShaderEntryPointName = "main",
|
||||
E_GEOMETRY_SHADER_TYPE gsCompileTarget = EGST_GS_4_0,
|
||||
scene::E_PRIMITIVE_TYPE inType = scene::EPT_TRIANGLES,
|
||||
scene::E_PRIMITIVE_TYPE outType = scene::EPT_TRIANGLE_STRIP,
|
||||
u32 verticesOut = 0,
|
||||
IShaderConstantSetCallBack* callback = 0,
|
||||
E_MATERIAL_TYPE baseMaterial = video::EMT_SOLID,
|
||||
s32 userData = 0,
|
||||
E_GPU_SHADING_LANGUAGE shadingLang = EGSL_DEFAULT);
|
||||
|
||||
void createMaterialRenderers();
|
||||
|
||||
void draw2D3DVertexPrimitiveList(const void* vertices,
|
||||
u32 vertexCount, const void* indexList, u32 primitiveCount,
|
||||
E_VERTEX_TYPE vType, scene::E_PRIMITIVE_TYPE pType,
|
||||
E_INDEX_TYPE iType, bool is3D);
|
||||
|
||||
D3DTEXTUREADDRESS getTextureWrapMode(const u8 clamp);
|
||||
|
||||
inline D3DCOLORVALUE colorToD3D(const SColor& col)
|
||||
{
|
||||
const f32 f = 1.0f / 255.0f;
|
||||
D3DCOLORVALUE v;
|
||||
v.r = col.getRed() * f;
|
||||
v.g = col.getGreen() * f;
|
||||
v.b = col.getBlue() * f;
|
||||
v.a = col.getAlpha() * f;
|
||||
return v;
|
||||
}
|
||||
|
||||
E_RENDER_MODE CurrentRenderMode;
|
||||
D3DPRESENT_PARAMETERS present;
|
||||
|
||||
SMaterial Material, LastMaterial;
|
||||
bool ResetRenderStates; // bool to make all renderstates be reseted if set.
|
||||
bool Transformation3DChanged;
|
||||
const ITexture* CurrentTexture[MATERIAL_MAX_TEXTURES];
|
||||
bool LastTextureMipMapsAvailable[MATERIAL_MAX_TEXTURES];
|
||||
core::matrix4 Matrices[ETS_COUNT]; // matrizes of the 3d mode we need to restore when we switch back from the 2d mode.
|
||||
|
||||
HINSTANCE D3DLibrary;
|
||||
IDirect3D9* pID3D;
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
|
||||
IDirect3DSurface9* PrevRenderTarget;
|
||||
core::dimension2d<u32> CurrentRendertargetSize;
|
||||
|
||||
HWND WindowId;
|
||||
core::rect<s32>* SceneSourceRect;
|
||||
|
||||
D3DCAPS9 Caps;
|
||||
|
||||
SIrrlichtCreationParameters Params;
|
||||
|
||||
E_VERTEX_TYPE LastVertexType;
|
||||
|
||||
SColorf AmbientLight;
|
||||
|
||||
core::stringc VendorName;
|
||||
u16 VendorID;
|
||||
|
||||
core::array<SDepthSurface*> DepthBuffers;
|
||||
|
||||
u32 MaxTextureUnits;
|
||||
u32 MaxUserClipPlanes;
|
||||
u32 MaxMRTs;
|
||||
u32 NumSetMRTs;
|
||||
f32 MaxLightDistance;
|
||||
s32 LastSetLight;
|
||||
|
||||
enum E_CACHE_2D_ATTRIBUTES
|
||||
{
|
||||
EC2D_ALPHA = 0x1,
|
||||
EC2D_TEXTURE = 0x2,
|
||||
EC2D_ALPHA_CHANNEL = 0x4
|
||||
};
|
||||
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
D3DFORMAT D3DColorFormat;
|
||||
bool DeviceLost;
|
||||
bool DriverWasReset;
|
||||
bool OcclusionQuerySupport;
|
||||
bool AlphaToCoverageSupport;
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_CG_
|
||||
CGcontext CgContext;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#endif // __C_VIDEO_DIRECTX_9_H_INCLUDED__
|
||||
|
@ -1,429 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#define _IRR_D3D_NO_SHADER_DEBUGGING 1
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9HLSLMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
|
||||
//! Public constructor
|
||||
CD3D9HLSLMaterialRenderer::CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver, s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, callback, baseMaterial, userData),
|
||||
VSConstantsTable(0), PSConstantsTable(0)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9HLSLMaterialRenderer");
|
||||
#endif
|
||||
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// now create shaders
|
||||
|
||||
if (vsCompileTarget < 0 || vsCompileTarget > EVST_COUNT)
|
||||
{
|
||||
os::Printer::log("Invalid HLSL vertex shader compilation target", ELL_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!createHLSLVertexShader(vertexShaderProgram,
|
||||
vertexShaderEntryPointName, VERTEX_SHADER_TYPE_NAMES[vsCompileTarget]))
|
||||
return;
|
||||
|
||||
if (!createHLSLPixelShader(pixelShaderProgram,
|
||||
pixelShaderEntryPointName, PIXEL_SHADER_TYPE_NAMES[psCompileTarget]))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D9HLSLMaterialRenderer::~CD3D9HLSLMaterialRenderer()
|
||||
{
|
||||
if (VSConstantsTable)
|
||||
VSConstantsTable->Release();
|
||||
|
||||
if (PSConstantsTable)
|
||||
PSConstantsTable->Release();
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::createHLSLVertexShader(const char* vertexShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName)
|
||||
{
|
||||
if (!vertexShaderProgram)
|
||||
return true;
|
||||
|
||||
LPD3DXBUFFER buffer = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile without debug info
|
||||
HRESULT h = stubD3DXCompileShader(
|
||||
vertexShaderProgram,
|
||||
strlen(vertexShaderProgram),
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
0, // no flags
|
||||
&buffer,
|
||||
&errors,
|
||||
&VSConstantsTable);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_hlsl_file_nr = 0;
|
||||
++irr_dbg_hlsl_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.vsh", irr_dbg_hlsl_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vertexShaderProgram, strlen(vertexShaderProgram), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
HRESULT h = stubD3DXCompileShaderFromFile(
|
||||
tmp,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION,
|
||||
&buffer,
|
||||
&errors,
|
||||
&VSConstantsTable);
|
||||
|
||||
#endif
|
||||
|
||||
if (FAILED(h))
|
||||
{
|
||||
os::Printer::log("HLSL vertex shader compilation failed:", ELL_ERROR);
|
||||
if (errors)
|
||||
{
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
errors->Release();
|
||||
if (buffer)
|
||||
buffer->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
errors->Release();
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
if (FAILED(pID3DDevice->CreateVertexShader((DWORD*)buffer->GetBufferPointer(),
|
||||
&VertexShader)))
|
||||
{
|
||||
os::Printer::log("Could not create hlsl vertex shader.", ELL_ERROR);
|
||||
buffer->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::createHLSLPixelShader(const char* pixelShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName)
|
||||
{
|
||||
if (!pixelShaderProgram)
|
||||
return true;
|
||||
|
||||
LPD3DXBUFFER buffer = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
DWORD flags = 0;
|
||||
|
||||
#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
|
||||
if (Driver->queryFeature(video::EVDF_VERTEX_SHADER_2_0) || Driver->queryFeature(video::EVDF_VERTEX_SHADER_3_0))
|
||||
// this one's for newer DX SDKs which don't support ps_1_x anymore
|
||||
// instead they'll silently compile 1_x as 2_x when using this flag
|
||||
flags |= D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY;
|
||||
#endif
|
||||
#if defined(_IRR_D3D_USE_LEGACY_HLSL_COMPILER) && defined(D3DXSHADER_USE_LEGACY_D3DX9_31_DLL)
|
||||
#ifdef D3DXSHADER_ENABLE_BACKWARDS_COMPATIBILITY
|
||||
else
|
||||
#endif
|
||||
flags |= D3DXSHADER_USE_LEGACY_D3DX9_31_DLL;
|
||||
#endif
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile without debug info
|
||||
HRESULT h = stubD3DXCompileShader(
|
||||
pixelShaderProgram,
|
||||
strlen(pixelShaderProgram),
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
flags,
|
||||
&buffer,
|
||||
&errors,
|
||||
&PSConstantsTable);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_hlsl_file_nr = 0;
|
||||
++irr_dbg_hlsl_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_hlsl_%d.psh", irr_dbg_hlsl_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pixelShaderProgram, strlen(pixelShaderProgram), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
HRESULT h = stubD3DXCompileShaderFromFile(
|
||||
tmp,
|
||||
0, // macros
|
||||
0, // no includes
|
||||
shaderEntryPointName,
|
||||
shaderTargetName,
|
||||
flags | D3DXSHADER_DEBUG | D3DXSHADER_SKIPOPTIMIZATION,
|
||||
&buffer,
|
||||
&errors,
|
||||
&PSConstantsTable);
|
||||
|
||||
#endif
|
||||
|
||||
if (FAILED(h))
|
||||
{
|
||||
os::Printer::log("HLSL pixel shader compilation failed:", ELL_ERROR);
|
||||
if (errors)
|
||||
{
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
errors->Release();
|
||||
if (buffer)
|
||||
buffer->Release();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (errors)
|
||||
errors->Release();
|
||||
|
||||
if (buffer)
|
||||
{
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)buffer->GetBufferPointer(),
|
||||
&PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create hlsl pixel shader.", ELL_ERROR);
|
||||
buffer->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const f32* floats, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetFloatArray(pID3DDevice, hndl, floats, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting float array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const bool* bools, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetBoolArray(pID3DDevice, hndl, (BOOL*)bools, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting bool array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::setVariable(bool vertexShader, const c8* name,
|
||||
const s32* ints, int count)
|
||||
{
|
||||
LPD3DXCONSTANTTABLE tbl = vertexShader ? VSConstantsTable : PSConstantsTable;
|
||||
if (!tbl)
|
||||
return false;
|
||||
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
D3DXHANDLE hndl = tbl->GetConstantByName(NULL, name);
|
||||
if (!hndl)
|
||||
{
|
||||
core::stringc s = "HLSL Variable to set not found: '";
|
||||
s += name;
|
||||
s += "'. Available variables are:";
|
||||
os::Printer::log(s.c_str(), ELL_WARNING);
|
||||
printHLSLVariables(tbl);
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DXCONSTANT_DESC Description;
|
||||
UINT ucount = 1;
|
||||
tbl->GetConstantDesc(hndl, &Description, &ucount);
|
||||
|
||||
if(Description.RegisterSet != D3DXRS_SAMPLER)
|
||||
{
|
||||
HRESULT hr = tbl->SetIntArray(pID3DDevice, hndl, ints, count);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Error setting int array for HLSL variable", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9HLSLMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (VSConstantsTable)
|
||||
VSConstantsTable->SetDefaults(pID3DDevice);
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9HLSLMaterialRenderer::printHLSLVariables(LPD3DXCONSTANTTABLE table)
|
||||
{
|
||||
// currently we only support top level parameters.
|
||||
// Should be enough for the beginning. (TODO)
|
||||
|
||||
// print out constant names
|
||||
D3DXCONSTANTTABLE_DESC tblDesc;
|
||||
HRESULT hr = table->GetDesc(&tblDesc);
|
||||
if (!FAILED(hr))
|
||||
{
|
||||
for (int i=0; i<(int)tblDesc.Constants; ++i)
|
||||
{
|
||||
D3DXCONSTANT_DESC d;
|
||||
UINT n = 1;
|
||||
D3DXHANDLE cHndl = table->GetConstant(NULL, i);
|
||||
if (!FAILED(table->GetConstantDesc(cHndl, &d, &n)))
|
||||
{
|
||||
core::stringc s = " '";
|
||||
s += d.Name;
|
||||
s += "' Registers:[begin:";
|
||||
s += (int)d.RegisterIndex;
|
||||
s += ", count:";
|
||||
s += (int)d.RegisterCount;
|
||||
s += "]";
|
||||
os::Printer::log(s.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
@ -1,85 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_HLSL_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IGPUProgrammingServices.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders via HLSL with D3D9
|
||||
class CD3D9HLSLMaterialRenderer : public CD3D9ShaderMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D9HLSLMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram,
|
||||
const c8* vertexShaderEntryPointName,
|
||||
E_VERTEX_SHADER_TYPE vsCompileTarget,
|
||||
const c8* pixelShaderProgram,
|
||||
const c8* pixelShaderEntryPointName,
|
||||
E_PIXEL_SHADER_TYPE psCompileTarget,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D9HLSLMaterialRenderer();
|
||||
|
||||
//! sets a variable in the shader.
|
||||
//! \param vertexShader: True if this should be set in the vertex shader, false if
|
||||
//! in the pixel shader.
|
||||
//! \param name: Name of the variable
|
||||
//! \param floats: Pointer to array of floats
|
||||
//! \param count: Amount of floats in array.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count);
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count);
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count);
|
||||
|
||||
bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
protected:
|
||||
|
||||
bool createHLSLVertexShader(const char* vertexShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName);
|
||||
|
||||
bool createHLSLPixelShader(const char* pixelShaderProgram,
|
||||
const char* shaderEntryPointName,
|
||||
const char* shaderTargetName);
|
||||
|
||||
void printHLSLVariables(LPD3DXCONSTANTTABLE table);
|
||||
|
||||
LPD3DXCONSTANTTABLE VSConstantsTable;
|
||||
LPD3DXCONSTANTTABLE PSConstantsTable;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,615 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
namespace
|
||||
{
|
||||
D3DMATRIX UnitMatrixD3D9;
|
||||
D3DMATRIX SphereMapMatrixD3D9;
|
||||
inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG2, arg2);
|
||||
}
|
||||
inline void setTextureColorStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_COLORARG1, arg1);
|
||||
}
|
||||
|
||||
inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i,
|
||||
DWORD arg1, DWORD op, DWORD arg2)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, op);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG2, arg2);
|
||||
}
|
||||
inline void setTextureAlphaStage(IDirect3DDevice9* dev, DWORD i, DWORD arg1)
|
||||
{
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1);
|
||||
dev->SetTextureStageState(i, D3DTSS_ALPHAARG1, arg1);
|
||||
}
|
||||
} // anonymous namespace
|
||||
|
||||
//! Base class for all internal D3D9 material renderers
|
||||
class CD3D9MaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Constructor
|
||||
CD3D9MaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver)
|
||||
: pID3DDevice(d3ddev), Driver(driver)
|
||||
{
|
||||
}
|
||||
|
||||
//! sets a variable in the shader.
|
||||
//! \param vertexShader: True if this should be set in the vertex shader, false if
|
||||
//! in the pixel shader.
|
||||
//! \param name: Name of the variable
|
||||
//! \param floats: Pointer to array of floats
|
||||
//! \param count: Amount of floats in array.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const f32* floats, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Bool interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const bool* bools, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
//! Int interface for the above.
|
||||
virtual bool setVariable(bool vertexShader, const c8* name, const s32* ints, int count)
|
||||
{
|
||||
os::Printer::log("Invalid material to set variable in.");
|
||||
return false;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
};
|
||||
|
||||
|
||||
//! Solid material renderer
|
||||
class CD3D9MaterialRenderer_SOLID : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SOLID(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
};
|
||||
|
||||
//! Generic Texture Blend
|
||||
class CD3D9MaterialRenderer_ONETEXTURE_BLEND : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_ONETEXTURE_BLEND(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType ||
|
||||
material.MaterialTypeParam != lastMaterial.MaterialTypeParam ||
|
||||
resetAllRenderstates)
|
||||
{
|
||||
|
||||
E_BLEND_FACTOR srcFact,dstFact;
|
||||
E_MODULATE_FUNC modulate;
|
||||
u32 alphaSource;
|
||||
unpack_textureBlendFunc ( srcFact, dstFact, modulate, alphaSource, material.MaterialTypeParam );
|
||||
|
||||
if (srcFact == EBF_SRC_COLOR && dstFact == EBF_ZERO)
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, getD3DBlend ( srcFact ) );
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, getD3DBlend ( dstFact ) );
|
||||
}
|
||||
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, getD3DModulate(modulate), D3DTA_DIFFUSE);
|
||||
|
||||
if ( textureBlendFunc_hasAlpha ( srcFact ) || textureBlendFunc_hasAlpha ( dstFact ) )
|
||||
{
|
||||
if (alphaSource==EAS_VERTEX_COLOR)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
}
|
||||
else if (alphaSource==EAS_TEXTURE)
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureAlphaStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
/** The scene management needs to know this for being able to sort the
|
||||
materials by opaque and transparent.
|
||||
The return value could be optimized, but we'd need to know the
|
||||
MaterialTypeParam for it. */
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
u32 getD3DBlend ( E_BLEND_FACTOR factor ) const
|
||||
{
|
||||
u32 r = 0;
|
||||
switch ( factor )
|
||||
{
|
||||
case EBF_ZERO: r = D3DBLEND_ZERO; break;
|
||||
case EBF_ONE: r = D3DBLEND_ONE; break;
|
||||
case EBF_DST_COLOR: r = D3DBLEND_DESTCOLOR; break;
|
||||
case EBF_ONE_MINUS_DST_COLOR: r = D3DBLEND_INVDESTCOLOR; break;
|
||||
case EBF_SRC_COLOR: r = D3DBLEND_SRCCOLOR; break;
|
||||
case EBF_ONE_MINUS_SRC_COLOR: r = D3DBLEND_INVSRCCOLOR; break;
|
||||
case EBF_SRC_ALPHA: r = D3DBLEND_SRCALPHA; break;
|
||||
case EBF_ONE_MINUS_SRC_ALPHA: r = D3DBLEND_INVSRCALPHA; break;
|
||||
case EBF_DST_ALPHA: r = D3DBLEND_DESTALPHA; break;
|
||||
case EBF_ONE_MINUS_DST_ALPHA: r = D3DBLEND_INVDESTALPHA; break;
|
||||
case EBF_SRC_ALPHA_SATURATE: r = D3DBLEND_SRCALPHASAT; break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
u32 getD3DModulate ( E_MODULATE_FUNC func ) const
|
||||
{
|
||||
u32 r = D3DTOP_MODULATE;
|
||||
switch ( func )
|
||||
{
|
||||
case EMFN_MODULATE_1X: r = D3DTOP_MODULATE; break;
|
||||
case EMFN_MODULATE_2X: r = D3DTOP_MODULATE2X; break;
|
||||
case EMFN_MODULATE_4X: r = D3DTOP_MODULATE4X; break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
bool transparent;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Solid 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_SOLID_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SOLID_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent add color material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ADD_COLOR(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_ONE);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCCOLOR);
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene management needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent vertex alpha material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_VERTEX_ALPHA(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates
|
||||
|| material.MaterialTypeParam != lastMaterial.MaterialTypeParam )
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, core::floor32(material.MaterialTypeParam * 255.f));
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! Transparent alpha channel material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_ALPHA_CHANNEL_REF(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
|
||||
// 127 is required by EMT_TRANSPARENT_ALPHA_CHANNEL_REF
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAREF, 127);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHATESTENABLE, FALSE);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return false; // this material is not really transparent because it does no blending.
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! material renderer for all kinds of lightmaps
|
||||
class CD3D9MaterialRenderer_LIGHTMAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_LIGHTMAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (material.MaterialType >= EMT_LIGHTMAP_LIGHTING)
|
||||
{
|
||||
// with lighting
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0, D3DTA_TEXTURE);
|
||||
}
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE,
|
||||
(material.MaterialType == EMT_LIGHTMAP_ADD)?
|
||||
D3DTOP_ADD:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M4 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M4)?
|
||||
D3DTOP_MODULATE4X:
|
||||
(material.MaterialType == EMT_LIGHTMAP_M2 || material.MaterialType == EMT_LIGHTMAP_LIGHTING_M2)?
|
||||
D3DTOP_MODULATE2X:
|
||||
D3DTOP_MODULATE,
|
||||
D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//! material renderer for detail maps
|
||||
class CD3D9MaterialRenderer_DETAIL_MAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_DETAIL_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_ADDSIGNED, D3DTA_CURRENT);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! sphere map material renderer
|
||||
class CD3D9MaterialRenderer_SPHERE_MAP : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_SPHERE_MAP(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, 0);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE0, &UnitMatrixD3D9 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
|
||||
pID3DDevice->SetTextureStageState( 1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform( D3DTS_TEXTURE1, &UnitMatrixD3D9 );
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//! reflection 2 layer material renderer
|
||||
class CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER : public CD3D9MaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9MaterialRenderer_TRANSPARENT_REFLECTION_2_LAYER(IDirect3DDevice9* p, video::IVideoDriver* d)
|
||||
: CD3D9MaterialRenderer(p, d) {}
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material, const SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, IMaterialRendererServices* services)
|
||||
{
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
setTextureColorStage(pID3DDevice, 0,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_DIFFUSE);
|
||||
setTextureAlphaStage(pID3DDevice, 0, D3DTA_DIFFUSE);
|
||||
setTextureColorStage(pID3DDevice, 1,
|
||||
D3DTA_TEXTURE, D3DTOP_MODULATE, D3DTA_CURRENT);
|
||||
setTextureAlphaStage(pID3DDevice, 1, D3DTA_CURRENT);
|
||||
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &SphereMapMatrixD3D9 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR);
|
||||
|
||||
pID3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
|
||||
pID3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
|
||||
pID3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnUnsetMaterial()
|
||||
{
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE);
|
||||
pID3DDevice->SetTextureStageState(1, D3DTSS_TEXCOORDINDEX, 1);
|
||||
pID3DDevice->SetTransform(D3DTS_TEXTURE1, &UnitMatrixD3D9);
|
||||
}
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
virtual bool isTransparent() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,306 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9NormalMapRenderer.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
// 1.1 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map vertex shader
|
||||
const char D3D9_NORMAL_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius^2 \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius^2 \n"\
|
||||
"vs.1.1\n"\
|
||||
"dcl_position v0 ; position \n"\
|
||||
"dcl_normal v1 ; normal \n"\
|
||||
"dcl_color v2 ; color \n"\
|
||||
"dcl_texcoord0 v3 ; texture coord \n"\
|
||||
"dcl_texcoord1 v4 ; tangent \n"\
|
||||
"dcl_texcoord2 v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - lightpos1\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - lightpos2\n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light vector 1 with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light vector 2 with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x^2 + r2.y^2 + r2.z^2 \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x^2 + r3.y^2 + r3.z^2 \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader
|
||||
const char D3D9_NORMAL_MAP_PSH_1_1[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
"ps.1.1 \n"\
|
||||
"tex t0 ; sample color map \n"\
|
||||
"tex t1 ; sample normal map\n"\
|
||||
"texcoord t2 ; fetch light vector 1\n"\
|
||||
"texcoord t3 ; fetch light vector 2\n"\
|
||||
"\n"\
|
||||
"dp3_sat r0, t1_bx2, t2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1)\n"\
|
||||
"mul r0, r0, v0 ; luminance1 * light color 1 \n"\
|
||||
"\n"\
|
||||
"dp3_sat r1, t1_bx2, t3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1)\n"\
|
||||
"mad r0, r1, v1, r0 ; (luminance2 * light color 2) + luminance 1 \n"\
|
||||
"\n"\
|
||||
"mul r0.xyz, t0, r0 ; total luminance * base color\n"\
|
||||
"+mov r0.a, v0.a ; write interpolated vertex alpha value \n"\
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
// Higher-quality normal map pixel shader (requires PS 2.0)
|
||||
// uses per-pixel normalization for improved accuracy
|
||||
const char D3D9_NORMAL_MAP_PSH_2_0[] =
|
||||
";Irrlicht Engine 0.8 D3D9 render path normal map pixel shader\n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
|
||||
"ps_2_0 \n"\
|
||||
"def c0, 0, 0, 0, 0\n"\
|
||||
"def c1, 1.0, 1.0, 1.0, 1.0\n"\
|
||||
"def c2, 2.0, 2.0, 2.0, 2.0\n"\
|
||||
"def c3, -.5, -.5, -.5, -.5\n"\
|
||||
"dcl t0\n"\
|
||||
"dcl t1\n"\
|
||||
"dcl t2\n"\
|
||||
"dcl t3\n"\
|
||||
"dcl v1\n"\
|
||||
"dcl v0\n"\
|
||||
"dcl_2d s0\n"\
|
||||
"dcl_2d s1\n"\
|
||||
|
||||
"texld r0, t0, s0 ; sample color map into r0 \n"\
|
||||
"texld r4, t0, s1 ; sample normal map into r4\n"\
|
||||
"add r4, r4, c3 ; bias the normal vector\n"\
|
||||
"add r5, t2, c3 ; bias the light 1 vector into r5\n"\
|
||||
"add r6, t3, c3 ; bias the light 2 vector into r6\n"\
|
||||
|
||||
"nrm r1, r4 ; normalize the normal vector into r1\n"\
|
||||
"nrm r2, r5 ; normalize the light1 vector into r2\n"\
|
||||
"nrm r3, r6 ; normalize the light2 vector into r3\n"\
|
||||
|
||||
"dp3 r2, r2, r1 ; let r2 = normal DOT light 1 vector\n"\
|
||||
"max r2, r2, c0 ; clamp result to positive numbers\n"\
|
||||
"mul r2, r2, v0 ; let r2 = luminance1 * light color 1 \n"\
|
||||
|
||||
"dp3 r3, r3, r1 ; let r3 = normal DOT light 2 vector\n"\
|
||||
"max r3, r3, c0 ; clamp result to positive numbers\n"\
|
||||
|
||||
"mad r2, r3, v1, r2 ; let r2 = (luminance2 * light color 2) + (luminance2 * light color 1) \n"\
|
||||
|
||||
"mul r2, r2, r0 ; let r2 = total luminance * base color\n"\
|
||||
"mov r2.w, v0.w ; write interpolated vertex alpha value \n"\
|
||||
|
||||
"mov oC0, r2 ; copy r2 to the output register \n"\
|
||||
|
||||
"\n"\
|
||||
"";
|
||||
|
||||
CD3D9NormalMapRenderer::CD3D9NormalMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9NormalMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basically, this thing simply compiles the hardcoded shaders
|
||||
// if the hardware is able to do them, otherwise it maps to the
|
||||
// base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled normal map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_NORMAL_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D9NormalMapRenderer* nmr = (video::CD3D9NormalMapRenderer*)renderer;
|
||||
VertexShader = nmr->VertexShader;
|
||||
if (VertexShader)
|
||||
VertexShader->AddRef();
|
||||
|
||||
PixelShader = nmr->PixelShader;
|
||||
if (PixelShader)
|
||||
PixelShader->AddRef();
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
// compile shaders on our own
|
||||
if (driver->queryFeature(video::EVDF_PIXEL_SHADER_2_0))
|
||||
{
|
||||
init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_2_0);
|
||||
}
|
||||
else
|
||||
{
|
||||
init(outMaterialTypeNr, D3D9_NORMAL_MAP_VSH, D3D9_NORMAL_MAP_PSH_1_1);
|
||||
}
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D9NormalMapRenderer::~CD3D9NormalMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9NormalMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Normal map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D9NormalMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_1) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D9NormalMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj(driver->getTransform(video::ETS_PROJECTION));
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
@ -1,56 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_NORMAL_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps
|
||||
class CD3D9NormalMapRenderer :
|
||||
public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9NormalMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
|
||||
~CD3D9NormalMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData);
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const;
|
||||
|
||||
private:
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,410 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "CD3D9ParallaxMapRenderer.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "SLight.h"
|
||||
|
||||
//#define SHADER_EXTERNAL_DEBUG
|
||||
|
||||
#ifdef SHADER_EXTERNAL_DEBUG
|
||||
#include "CReadFile.h"
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
// 1.1/1.4 Shaders with two lights and vertex based attenuation
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map vertex shader
|
||||
const char D3D9_PARALLAX_MAP_VSH[] =
|
||||
";Irrlicht Engine 0.10 D3D9 render path parallax mapping vertex shader\n"\
|
||||
"; c0-3: Transposed world matrix \n"\
|
||||
"; c4: Eye position \n"\
|
||||
"; c8-11: Transposed worldViewProj matrix (Projection * View * World) \n"\
|
||||
"; c12: Light01 position \n"\
|
||||
"; c13: x,y,z: Light01 color; .w: 1/LightRadius² \n"\
|
||||
"; c14: Light02 position \n"\
|
||||
"; c15: x,y,z: Light02 color; .w: 1/LightRadius² \n"\
|
||||
"vs.1.1\n"\
|
||||
"dcl_position v0 ; position \n"\
|
||||
"dcl_normal v1 ; normal \n"\
|
||||
"dcl_color v2 ; color \n"\
|
||||
"dcl_texcoord0 v3 ; texture coord \n"\
|
||||
"dcl_texcoord1 v4 ; tangent \n"\
|
||||
"dcl_texcoord2 v5 ; binormal \n"\
|
||||
"\n"\
|
||||
"def c95, 0.5, 0.5, 0.5, 0.5 ; used for moving light vector to ps \n"\
|
||||
"def c96, -1, 1, 1, 1 ; somewhere I've got a bug. flipping the vectors with this fixes it. \n"\
|
||||
"\n"\
|
||||
"m4x4 oPos, v0, c8 ; transform position to clip space with worldViewProj matrix\n"\
|
||||
"\n"\
|
||||
"m3x3 r5, v4, c0 ; transform tangent U\n"\
|
||||
"m3x3 r7, v1, c0 ; transform normal W\n"\
|
||||
"m3x3 r6, v5, c0 ; transform binormal V\n"\
|
||||
"\n"\
|
||||
"m4x4 r4, v0, c0 ; vertex into world position\n"\
|
||||
"add r2, c12, -r4 ; vtxpos - light1 pos\n"\
|
||||
"add r3, c14, -r4 ; vtxpos - light2 pos\n"\
|
||||
"add r1, -c4, r4 ; eye - vtxpos \n"\
|
||||
"\n"\
|
||||
"dp3 r8.x, r5, r2 ; transform the light1 vector with U, V, W\n"\
|
||||
"dp3 r8.y, r6, r2 \n"\
|
||||
"dp3 r8.z, r7, r2 \n"\
|
||||
"dp3 r9.x, r5, r3 ; transform the light2 vector with U, V, W\n"\
|
||||
"dp3 r9.y, r6, r3 \n"\
|
||||
"dp3 r9.z, r7, r3 \n"\
|
||||
"dp3 r10.x, r5, r1 ; transform the eye vector with U, V, W\n"\
|
||||
"dp3 r10.y, r6, r1 \n"\
|
||||
"dp3 r10.z, r7, r1 \n"\
|
||||
"\n"\
|
||||
"dp3 r8.w, r8, r8 ; normalize light vector 1 (r8)\n"\
|
||||
"rsq r8.w, r8.w \n"\
|
||||
"mul r8, r8, r8.w \n"\
|
||||
";mul r8, r8, c96 \n"\
|
||||
"dp3 r9.w, r9, r9 ; normalize light vector 2 (r9)\n"\
|
||||
"rsq r9.w, r9.w \n"\
|
||||
"mul r9, r9, r9.w \n"\
|
||||
";mul r9, r9, c96 \n"\
|
||||
"dp3 r10.w, r10, r10 ; normalize eye vector (r10)\n"\
|
||||
"rsq r10.w, r10.w \n"\
|
||||
"mul r10, r10, r10.w \n"\
|
||||
"mul r10, r10, c96 \n"\
|
||||
"\n"\
|
||||
"\n"\
|
||||
"mad oT2.xyz, r8.xyz, c95, c95 ; move light vector 1 from -1..1 into 0..1 \n"\
|
||||
"mad oT3.xyz, r9.xyz, c95, c95 ; move light vector 2 from -1..1 into 0..1 \n"\
|
||||
"mad oT4.xyz, r10.xyz, c95, c95 ; move eye vector from -1..1 into 0..1 \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 1 \n"\
|
||||
"dp3 r2.x, r2.xyz, r2.xyz ; r2.x = r2.x² + r2.y² + r2.z² \n"\
|
||||
"mul r2.x, r2.x, c13.w ; r2.x * attenutation \n"\
|
||||
"rsq r2, r2.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD0, r2, c13 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
" ; calculate attenuation of light 2 \n"\
|
||||
"dp3 r3.x, r3.xyz, r3.xyz ; r3.x = r3.x² + r3.y² + r3.z² \n"\
|
||||
"mul r3.x, r3.x, c15.w ; r2.x * attenutation \n"\
|
||||
"rsq r3, r3.x ; r2.xyzw = 1/sqrt(r2.x * attenutation)\n"\
|
||||
"mul oD1, r3, c15 ; resulting light color = lightcolor * attenuation \n"\
|
||||
"\n"\
|
||||
"mov oT0.xy, v3.xy ; move out texture coordinates 1\n"\
|
||||
"mov oT1.xy, v3.xy ; move out texture coordinates 2\n"\
|
||||
"mov oD0.a, v2.a ; move out original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader version 1.4
|
||||
const char D3D9_PARALLAX_MAP_PSH[] =
|
||||
";Irrlicht Engine 0.10 D3D9 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.1.4 \n"\
|
||||
" \n"\
|
||||
";def c6, 0.02f, 0.02f, 0.02f, 0.0f ; scale factor, now set in callback \n"\
|
||||
"def c5, 0.5f, 0.5f, 0.5f, 0.0f ; for specular division \n"\
|
||||
" \n"\
|
||||
"texld r1, t1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"texcrd r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"texcrd r0.xyz, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
";mul r3, r1_bx2.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to reduce swimming effect: \n"\
|
||||
"mul r3, r1_bx2.wwww, r1_bx2.zzzz ; (nh,nh,nh,nh) = (h,h,h,h) * (n.z,n.z,n.z,n.z,) \n"\
|
||||
"mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
"mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"phase \n"\
|
||||
" \n"\
|
||||
"texld r0, r2 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2 ; sample normal map \n"\
|
||||
"texcrd r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"texcrd r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r5, r1_bx2, r2_bx2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r5, r5, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1_bx2, r3_bx2 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r5 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"+mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"\n";
|
||||
|
||||
// Irrlicht Engine D3D9 render path normal map pixel shader version 2.0
|
||||
const char D3D9_PARALLAX_MAP_PSH_20[] =
|
||||
";Irrlicht Engine D3D9 render path parallax mapping pixel shader \n"\
|
||||
";Input: \n"\
|
||||
" \n"\
|
||||
";t0: color map texture coord \n"\
|
||||
";t1: normal map texture coords \n"\
|
||||
";t2: light 1 vector in tangent space \n"\
|
||||
";t4: eye vector in tangent space \n"\
|
||||
";v0: light 1 color \n"\
|
||||
";t3: light 2 vector in tangent space \n"\
|
||||
";v1: light 2 color \n"\
|
||||
";v0.a: vertex alpha value \n"\
|
||||
" \n"\
|
||||
"ps.2.0 \n"\
|
||||
" \n"\
|
||||
"dcl_2d s0 ; Declare the s0 register to be the sampler for stage 0 \n"\
|
||||
"dcl t0.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\
|
||||
"dcl t1.xy ; Declare t0 to have 2D texture coordinates from stage 0 \n"\
|
||||
"dcl_2d s1 ; Declare the s1 register to be the sampler for stage 1 \n"\
|
||||
" \n"\
|
||||
"dcl t2.xyz ; \n"\
|
||||
"dcl t3.xyz ; \n"\
|
||||
"dcl t4.xyz ; \n"\
|
||||
"dcl v0.xyzw; \n"\
|
||||
"dcl v1.xyzw; \n"\
|
||||
" \n"\
|
||||
"def c0, -1.0f, -1.0f, -1.0f, -1.0f ; for _bx2 emulation \n"\
|
||||
"def c1, 2.0f, 2.0f, 2.0f, 2.0f ; for _bx2 emulation \n"\
|
||||
"mov r11, c1; \n"\
|
||||
" \n"\
|
||||
"texld r1, t1, s1 ; sample (normal.x, normal.y, normal.z, height) \n"\
|
||||
"mov r4.xyz, t4 ; fetch eye vector \n"\
|
||||
"mov r0.xy, t0 ; color map \n"\
|
||||
" \n"\
|
||||
"; original parallax mapping: \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r1.xyz, r1, r11, c0; \n"\
|
||||
" \n"\
|
||||
"mul r3, r1.wwww, c6; ; r3 = (height, height, height) * scale \n"\
|
||||
" \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r4.xyz, r4, r11, c0; \n"\
|
||||
" \n"\
|
||||
"mad r2.xy, r3, r4, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"; modified parallax mapping to avoid swimming: \n"\
|
||||
";mul r3, r1_bx2.wwww, r1_bx2.zzzz ; r3 = (h,h,h,h) * (n.z, n.z, n.z, n.z,) \n"\
|
||||
";mul r3, r3, c6; ; r3 = (nh, nh, nh) * scale \n"\
|
||||
";mad r2.xyz, r3, r4_bx2, r0 ; newTexCoord = height * eye + oldTexCoord \n"\
|
||||
" \n"\
|
||||
"texld r0, r2, s0 ; load diffuse texture with new tex coord \n"\
|
||||
"texld r1, r2, s1 ; sample normal map \n"\
|
||||
"mov r2.xyz, t2 ; fetch light vector 1 \n"\
|
||||
"mov r3.xyz, t3 ; fetch light vector 2 \n"\
|
||||
" \n"\
|
||||
"; emulate ps1x _bx2, so substract 0.5f and multiply by 2 \n"\
|
||||
"mad r1.xyz, r1, r11, c0; \n"\
|
||||
"mad r2.xyz, r2, r11, c0; \n"\
|
||||
"mad r3.xyz, r3, r11, c0; \n"\
|
||||
" \n"\
|
||||
"dp3_sat r2, r1, r2 ; normal dot light 1 (_bx2 because moved into 0..1) \n"\
|
||||
"mul r2, r2, v0 ; luminance1 * light color 1 \n"\
|
||||
" \n"\
|
||||
"dp3_sat r3, r1, r3 ; normal dot light 2 (_bx2 because moved into 0..1) \n"\
|
||||
"mad r3, r3, v1, r2 ; (luminance2 * light color 2) + luminance1 \n"\
|
||||
" \n"\
|
||||
"mul r0.xyz, r0, r3 ; total luminance * base color \n"\
|
||||
"mov r0.a, v0.a ; write original alpha value \n"\
|
||||
"mov oC0, r0; \n"\
|
||||
"\n";
|
||||
|
||||
CD3D9ParallaxMapRenderer::CD3D9ParallaxMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial)
|
||||
: CD3D9ShaderMaterialRenderer(d3ddev, driver, 0, baseMaterial),
|
||||
CurrentScale(0.0f)
|
||||
{
|
||||
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ParallaxMapRenderer");
|
||||
#endif
|
||||
|
||||
// set this as callback. We could have done this in
|
||||
// the initialization list, but some compilers don't like it.
|
||||
|
||||
CallBack = this;
|
||||
|
||||
// basicly, this thing simply compiles these hardcoded shaders if the
|
||||
// hardware is able to do them, otherwise it maps to the base material
|
||||
|
||||
if (!driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) ||
|
||||
!driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
{
|
||||
// this hardware is not able to do shaders. Fall back to
|
||||
// base material.
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if already compiled parallax map shaders are there.
|
||||
|
||||
video::IMaterialRenderer* renderer = driver->getMaterialRenderer(EMT_PARALLAX_MAP_SOLID);
|
||||
if (renderer)
|
||||
{
|
||||
// use the already compiled shaders
|
||||
video::CD3D9ParallaxMapRenderer* nmr = (video::CD3D9ParallaxMapRenderer*)renderer;
|
||||
VertexShader = nmr->VertexShader;
|
||||
if (VertexShader)
|
||||
VertexShader->AddRef();
|
||||
|
||||
PixelShader = nmr->PixelShader;
|
||||
if (PixelShader)
|
||||
PixelShader->AddRef();
|
||||
|
||||
outMaterialTypeNr = driver->addMaterialRenderer(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef SHADER_EXTERNAL_DEBUG
|
||||
|
||||
// quickly load shader from external file
|
||||
io::CReadFile* file = new io::CReadFile("parallax.psh");
|
||||
s32 sz = file->getSize();
|
||||
char* s = new char[sz+1];
|
||||
file->read(s, sz);
|
||||
s[sz] = 0;
|
||||
|
||||
init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, s);
|
||||
|
||||
delete [] s;
|
||||
file->drop();
|
||||
|
||||
#else
|
||||
|
||||
// compile shaders on our own
|
||||
init(outMaterialTypeNr, D3D9_PARALLAX_MAP_VSH, D3D9_PARALLAX_MAP_PSH);
|
||||
|
||||
#endif // SHADER_EXTERNAL_DEBUG
|
||||
}
|
||||
// something failed, use base material
|
||||
if (-1==outMaterialTypeNr)
|
||||
driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
CD3D9ParallaxMapRenderer::~CD3D9ParallaxMapRenderer()
|
||||
{
|
||||
if (CallBack == this)
|
||||
CallBack = 0;
|
||||
}
|
||||
|
||||
bool CD3D9ParallaxMapRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
if (vtxtype != video::EVT_TANGENTS)
|
||||
{
|
||||
os::Printer::log("Error: Parallax map renderer only supports vertices of type EVT_TANGENTS", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
return CD3D9ShaderMaterialRenderer::OnRender(service, vtxtype);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ParallaxMapRenderer::OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
CD3D9ShaderMaterialRenderer::OnSetMaterial(material, lastMaterial,
|
||||
resetAllRenderstates, services);
|
||||
|
||||
CurrentScale = material.MaterialTypeParam;
|
||||
}
|
||||
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
s32 CD3D9ParallaxMapRenderer::getRenderCapability() const
|
||||
{
|
||||
if (Driver->queryFeature(video::EVDF_PIXEL_SHADER_1_4) &&
|
||||
Driver->queryFeature(video::EVDF_VERTEX_SHADER_1_1))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants
|
||||
//! for an material renderer should be set.
|
||||
void CD3D9ParallaxMapRenderer::OnSetConstants(IMaterialRendererServices* services, s32 userData)
|
||||
{
|
||||
video::IVideoDriver* driver = services->getVideoDriver();
|
||||
|
||||
// set transposed world matrix
|
||||
services->setVertexShaderConstant(driver->getTransform(video::ETS_WORLD).getTransposed().pointer(), 0, 4);
|
||||
|
||||
// set eye position
|
||||
|
||||
// The viewpoint is at (0., 0., 0.) in eye space.
|
||||
// Turning this into a vector [0 0 0 1] and multiply it by
|
||||
// the inverse of the view matrix, the resulting vector is the
|
||||
// object space location of the camera.
|
||||
|
||||
f32 floats[4] = {0,0,0,1};
|
||||
core::matrix4 minv = driver->getTransform(video::ETS_VIEW);
|
||||
minv.makeInverse();
|
||||
minv.multiplyWith1x4Matrix(floats);
|
||||
services->setVertexShaderConstant(floats, 4, 1);
|
||||
|
||||
// set transposed worldViewProj matrix
|
||||
core::matrix4 worldViewProj;
|
||||
worldViewProj = driver->getTransform(video::ETS_PROJECTION);
|
||||
worldViewProj *= driver->getTransform(video::ETS_VIEW);
|
||||
worldViewProj *= driver->getTransform(video::ETS_WORLD);
|
||||
services->setVertexShaderConstant(worldViewProj.getTransposed().pointer(), 8, 4);
|
||||
|
||||
// here we've got to fetch the fixed function lights from the
|
||||
// driver and set them as constants
|
||||
|
||||
const u32 cnt = driver->getDynamicLightCount();
|
||||
|
||||
for (u32 i=0; i<2; ++i)
|
||||
{
|
||||
SLight light;
|
||||
|
||||
if (i<cnt)
|
||||
light = driver->getDynamicLight(i);
|
||||
else
|
||||
{
|
||||
light.DiffuseColor.set(0,0,0); // make light dark
|
||||
light.Radius = 1.0f;
|
||||
}
|
||||
|
||||
light.DiffuseColor.a = 1.0f/(light.Radius*light.Radius); // set attenuation
|
||||
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.Position), 12+(i*2), 1);
|
||||
services->setVertexShaderConstant(reinterpret_cast<const f32*>(&light.DiffuseColor), 13+(i*2), 1);
|
||||
}
|
||||
|
||||
// this is not really necessary in d3d9 (used a def instruction), but to be sure:
|
||||
f32 c95[] = {0.5f, 0.5f, 0.5f, 0.5f};
|
||||
services->setVertexShaderConstant(c95, 95, 1);
|
||||
f32 c96[] = {-1, 1, 1, 1};
|
||||
services->setVertexShaderConstant(c96, 96, 1);
|
||||
|
||||
// set scale factor
|
||||
f32 factor = 0.02f; // default value
|
||||
if (CurrentScale != 0)
|
||||
factor = CurrentScale;
|
||||
|
||||
f32 c6[] = {factor, factor, factor, 0};
|
||||
services->setPixelShaderConstant(c6, 6, 1);
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
@ -1,63 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_PARALLAX_MAPMATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Renderer for normal maps using parallax mapping
|
||||
class CD3D9ParallaxMapRenderer :
|
||||
public CD3D9ShaderMaterialRenderer, IShaderConstantSetCallBack
|
||||
{
|
||||
public:
|
||||
|
||||
CD3D9ParallaxMapRenderer(
|
||||
IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, IMaterialRenderer* baseMaterial);
|
||||
|
||||
~CD3D9ParallaxMapRenderer();
|
||||
|
||||
//! Called by the engine when the vertex and/or pixel shader constants for an
|
||||
//! material renderer should be set.
|
||||
virtual void OnSetConstants(IMaterialRendererServices* services, s32 userData);
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns the render capability of the material.
|
||||
virtual s32 getRenderCapability() const;
|
||||
|
||||
virtual void OnSetMaterial(const SMaterial& material) { }
|
||||
virtual void OnSetMaterial(const video::SMaterial& material,
|
||||
const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services);
|
||||
|
||||
private:
|
||||
|
||||
f32 CurrentScale;
|
||||
|
||||
};
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,541 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#define _IRR_D3D_NO_SHADER_DEBUGGING 1
|
||||
|
||||
#include "CD3D9ShaderMaterialRenderer.h"
|
||||
#include "IShaderConstantSetCallBack.h"
|
||||
#include "IMaterialRendererServices.h"
|
||||
#include "IVideoDriver.h"
|
||||
#include "os.h"
|
||||
#include "irrString.h"
|
||||
|
||||
#ifndef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! Public constructor
|
||||
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
|
||||
init(outMaterialTypeNr, vertexShaderProgram, pixelShaderProgram);
|
||||
}
|
||||
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D9ShaderMaterialRenderer::CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial, s32 userData)
|
||||
: pID3DDevice(d3ddev), Driver(driver), CallBack(callback), BaseMaterial(baseMaterial),
|
||||
VertexShader(0), OldVertexShader(0), PixelShader(0), UserData(userData)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9ShaderMaterialRenderer");
|
||||
#endif
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->grab();
|
||||
|
||||
if (CallBack)
|
||||
CallBack->grab();
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::init(s32& outMaterialTypeNr,
|
||||
const c8* vertexShaderProgram, const c8* pixelShaderProgram)
|
||||
{
|
||||
outMaterialTypeNr = -1;
|
||||
|
||||
// create vertex shader
|
||||
if (!createVertexShader(vertexShaderProgram))
|
||||
return;
|
||||
|
||||
// create pixel shader
|
||||
if (!createPixelShader(pixelShaderProgram))
|
||||
return;
|
||||
|
||||
// register myself as new material
|
||||
outMaterialTypeNr = Driver->addMaterialRenderer(this);
|
||||
}
|
||||
|
||||
|
||||
//! Destructor
|
||||
CD3D9ShaderMaterialRenderer::~CD3D9ShaderMaterialRenderer()
|
||||
{
|
||||
if (CallBack)
|
||||
CallBack->drop();
|
||||
|
||||
if (VertexShader)
|
||||
VertexShader->Release();
|
||||
|
||||
if (PixelShader)
|
||||
PixelShader->Release();
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->drop();
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype)
|
||||
{
|
||||
// call callback to set shader constants
|
||||
if (CallBack && (VertexShader || PixelShader))
|
||||
CallBack->OnSetConstants(service, UserData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services)
|
||||
{
|
||||
if (material.MaterialType != lastMaterial.MaterialType || resetAllRenderstates)
|
||||
{
|
||||
if (VertexShader)
|
||||
{
|
||||
// save old vertex shader
|
||||
pID3DDevice->GetVertexShader(&OldVertexShader);
|
||||
|
||||
// set new vertex shader
|
||||
if (FAILED(pID3DDevice->SetVertexShader(VertexShader)))
|
||||
os::Printer::log("Could not set vertex shader.", ELL_WARNING);
|
||||
}
|
||||
|
||||
// set new pixel shader
|
||||
if (PixelShader)
|
||||
{
|
||||
if (FAILED(pID3DDevice->SetPixelShader(PixelShader)))
|
||||
os::Printer::log("Could not set pixel shader.", ELL_WARNING);
|
||||
}
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnSetMaterial(material, material, true, services);
|
||||
}
|
||||
|
||||
//let callback know used material
|
||||
if (CallBack)
|
||||
CallBack->OnSetMaterial(material);
|
||||
|
||||
services->setBasicRenderStates(material, lastMaterial, resetAllRenderstates);
|
||||
}
|
||||
|
||||
|
||||
void CD3D9ShaderMaterialRenderer::OnUnsetMaterial()
|
||||
{
|
||||
if (VertexShader)
|
||||
pID3DDevice->SetVertexShader(OldVertexShader);
|
||||
|
||||
if (PixelShader)
|
||||
pID3DDevice->SetPixelShader(0);
|
||||
|
||||
if (BaseMaterial)
|
||||
BaseMaterial->OnUnsetMaterial();
|
||||
}
|
||||
|
||||
|
||||
//! Returns if the material is transparent. The scene managment needs to know this
|
||||
//! for being able to sort the materials by opaque and transparent.
|
||||
bool CD3D9ShaderMaterialRenderer::isTransparent() const
|
||||
{
|
||||
return BaseMaterial ? BaseMaterial->isTransparent() : false;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::createPixelShader(const c8* pxsh)
|
||||
{
|
||||
if (!pxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
stubD3DXAssembleShader(pxsh, (UINT)strlen(pxsh), 0, 0, 0, &code, &errors);
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_shader_%d.psh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(pxsh, strlen(pxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Pixel shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(pID3DDevice->CreatePixelShader((DWORD*)code->GetBufferPointer(), &PixelShader)))
|
||||
{
|
||||
os::Printer::log("Could not create pixel shader.", ELL_ERROR);
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9ShaderMaterialRenderer::createVertexShader(const char* vtxsh)
|
||||
{
|
||||
if (!vtxsh)
|
||||
return true;
|
||||
|
||||
// compile shader
|
||||
|
||||
LPD3DXBUFFER code = 0;
|
||||
LPD3DXBUFFER errors = 0;
|
||||
|
||||
#ifdef _IRR_D3D_NO_SHADER_DEBUGGING
|
||||
|
||||
// compile shader without debug info
|
||||
stubD3DXAssembleShader(vtxsh, (UINT)strlen(vtxsh), 0, 0, 0, &code, &errors);
|
||||
|
||||
#else
|
||||
|
||||
// compile shader and emitt some debug informations to
|
||||
// make it possible to debug the shader in visual studio
|
||||
|
||||
static int irr_dbg_file_nr = 0;
|
||||
++irr_dbg_file_nr;
|
||||
char tmp[32];
|
||||
sprintf(tmp, "irr_d3d9_dbg_shader_%d.vsh", irr_dbg_file_nr);
|
||||
|
||||
FILE* f = fopen(tmp, "wb");
|
||||
fwrite(vtxsh, strlen(vtxsh), 1, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
|
||||
stubD3DXAssembleShaderFromFile(tmp, 0, 0, D3DXSHADER_DEBUG, &code, &errors);
|
||||
|
||||
#endif
|
||||
|
||||
if (errors)
|
||||
{
|
||||
// print out compilation errors.
|
||||
os::Printer::log("Vertex shader compilation failed:", ELL_ERROR);
|
||||
os::Printer::log((c8*)errors->GetBufferPointer(), ELL_ERROR);
|
||||
|
||||
if (code)
|
||||
code->Release();
|
||||
|
||||
errors->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!code || FAILED(pID3DDevice->CreateVertexShader((DWORD*)code->GetBufferPointer(), &VertexShader)))
|
||||
{
|
||||
os::Printer::log("Could not create vertex shader.", ELL_ERROR);
|
||||
if (code)
|
||||
code->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
code->Release();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader(LPCSTR pSrcData,
|
||||
UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs)
|
||||
{
|
||||
// Because Irrlicht needs to be able to start up even without installed d3d dlls, it
|
||||
// needs to load external d3d dlls manually. examples for the dlls are:
|
||||
// SDK dll name D3DX_SDK_VERSION
|
||||
// Summer 2004: no dll 22
|
||||
// February 2005: d3dx9_24.dll 24
|
||||
// April 2005: d3dx9_25.dll 25
|
||||
// June 2005: d3dx9_26.dll 26
|
||||
// August 2005: d3dx9_27.dll 27
|
||||
// October 2005,
|
||||
// December 2005: d3dx9_28.dll 28
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXAssembleShader(pSrcData, SrcDataLen, pDefines, pInclude,
|
||||
Flags, ppShader, ppErrorMsgs);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXAssembleShader signature
|
||||
typedef HRESULT (WINAPI *AssembleShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
|
||||
DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static AssembleShaderFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibraryA(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (AssembleShaderFunction)GetProcAddress(hMod, "D3DXAssembleShader");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXAssembleShader from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXAssembleShaderFromFileA(pSrcFile, pDefines, pInclude, Flags,
|
||||
ppShader, ppErrorMsgs);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXAssembleShaderFromFileA signature
|
||||
typedef HRESULT (WINAPI *AssembleShaderFromFileFunction)(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static AssembleShaderFromFileFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibraryA(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (AssembleShaderFromFileFunction)GetProcAddress(hMod, "D3DXAssembleShaderFromFileA");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXAssembleShaderFromFileA from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcFile, pDefines, pInclude, Flags, ppShader, ppErrorMsgs);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXCompileShader(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXCompileShader
|
||||
typedef HRESULT (WINAPI *D3DXCompileShaderFunction)(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static D3DXCompileShaderFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibraryA(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (D3DXCompileShaderFunction)GetProcAddress(hMod, "D3DXCompileShader");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXCompileShader from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcData, SrcDataLen, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
HRESULT CD3D9ShaderMaterialRenderer::stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable)
|
||||
{
|
||||
// wondering what I'm doing here?
|
||||
// see comment in CD3D9ShaderMaterialRenderer::stubD3DXAssembleShader()
|
||||
|
||||
#if ( D3DX_SDK_VERSION < 24 )
|
||||
// directly link functions, old d3d sdks didn't try to load external dlls
|
||||
// when linking to the d3dx9.lib
|
||||
#ifdef _MSC_VER
|
||||
#pragma comment (lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
// invoke static linked function
|
||||
return D3DXCompileShaderFromFileA(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
#else
|
||||
{
|
||||
// try to load shader functions from the dll and print error if failed.
|
||||
|
||||
// D3DXCompileShaderFromFileA
|
||||
typedef HRESULT (WINAPI *D3DXCompileShaderFromFileFunction)(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
static bool LoadFailed = false;
|
||||
static D3DXCompileShaderFromFileFunction pFn = 0;
|
||||
|
||||
if (!pFn && !LoadFailed)
|
||||
{
|
||||
// try to load dll
|
||||
io::path strDllName = "d3dx9_";
|
||||
strDllName += (int)D3DX_SDK_VERSION;
|
||||
strDllName += ".dll";
|
||||
|
||||
HMODULE hMod = LoadLibraryA(strDllName.c_str());
|
||||
if (hMod)
|
||||
pFn = (D3DXCompileShaderFromFileFunction)GetProcAddress(hMod, "D3DXCompileShaderFromFileA");
|
||||
|
||||
if (!pFn)
|
||||
{
|
||||
LoadFailed = true;
|
||||
os::Printer::log("Could not load shader function D3DXCompileShaderFromFileA from dll, shaders disabled",
|
||||
strDllName.c_str(), ELL_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
if (pFn)
|
||||
{
|
||||
// call already loaded function
|
||||
return (*pFn)(pSrcFile, pDefines, pInclude, pFunctionName, pProfile, Flags, ppShader, ppErrorMsgs, ppConstantTable);
|
||||
}
|
||||
}
|
||||
#endif // D3DX_SDK_VERSION < 24
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
@ -1,102 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
#define __C_D3D9_SHADER_MATERIAL_RENDERER_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_WINDOWS_
|
||||
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3dx9shader.h>
|
||||
|
||||
#include "IMaterialRenderer.h"
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class IVideoDriver;
|
||||
class IShaderConstantSetCallBack;
|
||||
class IMaterialRenderer;
|
||||
|
||||
//! Class for using vertex and pixel shaders with D3D9
|
||||
class CD3D9ShaderMaterialRenderer : public IMaterialRenderer
|
||||
{
|
||||
public:
|
||||
|
||||
//! Public constructor
|
||||
CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev, video::IVideoDriver* driver,
|
||||
s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram,
|
||||
IShaderConstantSetCallBack* callback, IMaterialRenderer* baseMaterial, s32 userData);
|
||||
|
||||
//! Destructor
|
||||
~CD3D9ShaderMaterialRenderer();
|
||||
|
||||
virtual void OnSetMaterial(const video::SMaterial& material, const video::SMaterial& lastMaterial,
|
||||
bool resetAllRenderstates, video::IMaterialRendererServices* services);
|
||||
|
||||
virtual void OnUnsetMaterial();
|
||||
|
||||
virtual bool OnRender(IMaterialRendererServices* service, E_VERTEX_TYPE vtxtype);
|
||||
|
||||
//! Returns if the material is transparent.
|
||||
virtual bool isTransparent() const;
|
||||
|
||||
protected:
|
||||
|
||||
//! constructor only for use by derived classes who want to
|
||||
//! create a fall back material for example.
|
||||
CD3D9ShaderMaterialRenderer(IDirect3DDevice9* d3ddev,
|
||||
video::IVideoDriver* driver,
|
||||
IShaderConstantSetCallBack* callback,
|
||||
IMaterialRenderer* baseMaterial,
|
||||
s32 userData=0);
|
||||
|
||||
void init(s32& outMaterialTypeNr, const c8* vertexShaderProgram, const c8* pixelShaderProgram);
|
||||
bool createPixelShader(const c8* pxsh);
|
||||
bool createVertexShader(const char* vtxsh);
|
||||
|
||||
HRESULT stubD3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude,
|
||||
DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
HRESULT stubD3DXAssembleShaderFromFile(LPCSTR pSrcFile,
|
||||
CONST D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags,
|
||||
LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs);
|
||||
|
||||
HRESULT stubD3DXCompileShader(LPCSTR pSrcData, UINT SrcDataLen, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader,
|
||||
LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
HRESULT stubD3DXCompileShaderFromFile(LPCSTR pSrcFile, CONST D3DXMACRO* pDefines,
|
||||
LPD3DXINCLUDE pInclude, LPCSTR pFunctionName,
|
||||
LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs,
|
||||
LPD3DXCONSTANTTABLE* ppConstantTable);
|
||||
|
||||
IDirect3DDevice9* pID3DDevice;
|
||||
video::IVideoDriver* Driver;
|
||||
IShaderConstantSetCallBack* CallBack;
|
||||
IMaterialRenderer* BaseMaterial;
|
||||
|
||||
IDirect3DVertexShader9* VertexShader;
|
||||
IDirect3DVertexShader9* OldVertexShader;
|
||||
IDirect3DPixelShader9* PixelShader;
|
||||
s32 UserData;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
@ -1,699 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#define _IRR_DONT_DO_MEMORY_DEBUGGING_HERE
|
||||
#include "CD3D9Texture.h"
|
||||
#include "CD3D9Driver.h"
|
||||
#include "os.h"
|
||||
|
||||
#include <d3dx9tex.h>
|
||||
|
||||
#ifndef _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation in d3d 8 when
|
||||
// compiling with both D3D 8 and 9.
|
||||
// #define _IRR_USE_D3DXFilterTexture_
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_8_
|
||||
|
||||
#ifdef _IRR_USE_D3DXFilterTexture_
|
||||
#pragma comment(lib, "d3dx9.lib")
|
||||
#endif
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
//! rendertarget constructor
|
||||
CD3D9Texture::CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size,
|
||||
const io::path& name, const ECOLOR_FORMAT format)
|
||||
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
|
||||
TextureSize(size), ImageSize(size), Pitch(0), ColorFormat(ECF_UNKNOWN),
|
||||
HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(true)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9Texture");
|
||||
#endif
|
||||
|
||||
Device=driver->getExposedVideoData().D3D9.D3DDev9;
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
createRenderTarget(format);
|
||||
}
|
||||
|
||||
|
||||
//! constructor
|
||||
CD3D9Texture::CD3D9Texture(IImage* image, CD3D9Driver* driver,
|
||||
u32 flags, const io::path& name, void* mipmapData)
|
||||
: ITexture(name), Texture(0), RTTSurface(0), Driver(driver), DepthSurface(0),
|
||||
TextureSize(0,0), ImageSize(0,0), Pitch(0), ColorFormat(ECF_UNKNOWN),
|
||||
HasMipMaps(false), HardwareMipMaps(false), IsRenderTarget(false)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
setDebugName("CD3D9Texture");
|
||||
#endif
|
||||
|
||||
HasMipMaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
|
||||
Device=driver->getExposedVideoData().D3D9.D3DDev9;
|
||||
if (Device)
|
||||
Device->AddRef();
|
||||
|
||||
if (image)
|
||||
{
|
||||
if (createTexture(flags, image))
|
||||
{
|
||||
if (copyTexture(image))
|
||||
{
|
||||
regenerateMipMapLevels(mipmapData);
|
||||
}
|
||||
}
|
||||
else
|
||||
os::Printer::log("Could not create DIRECT3D9 Texture.", ELL_WARNING);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! destructor
|
||||
CD3D9Texture::~CD3D9Texture()
|
||||
{
|
||||
if (Texture)
|
||||
Texture->Release();
|
||||
|
||||
if (RTTSurface)
|
||||
RTTSurface->Release();
|
||||
|
||||
// if this texture was the last one using the depth buffer
|
||||
// we can release the surface. We only use the value of the pointer
|
||||
// hence it is safe to use the dropped pointer...
|
||||
if (DepthSurface)
|
||||
{
|
||||
if (DepthSurface->drop())
|
||||
Driver->removeDepthSurface(DepthSurface);
|
||||
}
|
||||
|
||||
if (Device)
|
||||
Device->Release();
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::createRenderTarget(const ECOLOR_FORMAT format)
|
||||
{
|
||||
// are texture size restrictions there ?
|
||||
if(!Driver->queryFeature(EVDF_TEXTURE_NPOT))
|
||||
{
|
||||
if (TextureSize != ImageSize)
|
||||
os::Printer::log("RenderTarget size has to be a power of two", ELL_INFORMATION);
|
||||
}
|
||||
TextureSize = TextureSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
D3DFORMAT d3dformat = Driver->getD3DColorFormat();
|
||||
|
||||
if(ColorFormat == ECF_UNKNOWN)
|
||||
{
|
||||
// get irrlicht format from backbuffer
|
||||
// (This will get overwritten by the custom format if it is provided, else kept.)
|
||||
ColorFormat = Driver->getColorFormat();
|
||||
setPitch(d3dformat);
|
||||
|
||||
// Use color format if provided.
|
||||
if(format != ECF_UNKNOWN)
|
||||
{
|
||||
ColorFormat = format;
|
||||
d3dformat = Driver->getD3DFormatFromColorFormat(format);
|
||||
setPitch(d3dformat); // This will likely set pitch to 0 for now.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
d3dformat = Driver->getD3DFormatFromColorFormat(ColorFormat);
|
||||
}
|
||||
|
||||
// create texture
|
||||
HRESULT hr;
|
||||
|
||||
hr = Device->CreateTexture(
|
||||
TextureSize.Width,
|
||||
TextureSize.Height,
|
||||
1, // mip map level count, we don't want mipmaps here
|
||||
D3DUSAGE_RENDERTARGET,
|
||||
d3dformat,
|
||||
D3DPOOL_DEFAULT,
|
||||
&Texture,
|
||||
NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
if (D3DERR_INVALIDCALL == hr)
|
||||
os::Printer::log("Could not create render target texture", "Invalid Call");
|
||||
else
|
||||
if (D3DERR_OUTOFVIDEOMEMORY == hr)
|
||||
os::Printer::log("Could not create render target texture", "Out of Video Memory");
|
||||
else
|
||||
if (E_OUTOFMEMORY == hr)
|
||||
os::Printer::log("Could not create render target texture", "Out of Memory");
|
||||
else
|
||||
os::Printer::log("Could not create render target texture");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool CD3D9Texture::createMipMaps(u32 level)
|
||||
{
|
||||
if (level==0)
|
||||
return true;
|
||||
|
||||
if (HardwareMipMaps && Texture)
|
||||
{
|
||||
// generate mipmaps in hardware
|
||||
Texture->GenerateMipSubLevels();
|
||||
return true;
|
||||
}
|
||||
|
||||
// manual mipmap generation
|
||||
IDirect3DSurface9* upperSurface = 0;
|
||||
IDirect3DSurface9* lowerSurface = 0;
|
||||
|
||||
// get upper level
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level-1, &upperSurface);
|
||||
if (FAILED(hr) || !upperSurface)
|
||||
{
|
||||
os::Printer::log("Could not get upper surface level for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// get lower level
|
||||
hr = Texture->GetSurfaceLevel(level, &lowerSurface);
|
||||
if (FAILED(hr) || !lowerSurface)
|
||||
{
|
||||
os::Printer::log("Could not get lower surface level for mip map generation", ELL_WARNING);
|
||||
upperSurface->Release();
|
||||
return false;
|
||||
}
|
||||
|
||||
D3DSURFACE_DESC upperDesc, lowerDesc;
|
||||
upperSurface->GetDesc(&upperDesc);
|
||||
lowerSurface->GetDesc(&lowerDesc);
|
||||
|
||||
D3DLOCKED_RECT upperlr;
|
||||
D3DLOCKED_RECT lowerlr;
|
||||
|
||||
// lock upper surface
|
||||
if (FAILED(upperSurface->LockRect(&upperlr, NULL, 0)))
|
||||
{
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
os::Printer::log("Could not lock upper texture for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
// lock lower surface
|
||||
if (FAILED(lowerSurface->LockRect(&lowerlr, NULL, 0)))
|
||||
{
|
||||
upperSurface->UnlockRect();
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
os::Printer::log("Could not lock lower texture for mip map generation", ELL_WARNING);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (upperDesc.Format != lowerDesc.Format)
|
||||
{
|
||||
os::Printer::log("Cannot copy mip maps with different formats.", ELL_WARNING);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((upperDesc.Format == D3DFMT_A1R5G5B5) || (upperDesc.Format == D3DFMT_R5G6B5))
|
||||
copy16BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
if (upperDesc.Format == D3DFMT_A8R8G8B8)
|
||||
copy32BitMipMap((char*)upperlr.pBits, (char*)lowerlr.pBits,
|
||||
lowerDesc.Width, lowerDesc.Height,
|
||||
upperlr.Pitch, lowerlr.Pitch);
|
||||
else
|
||||
os::Printer::log("Unsupported mipmap format, cannot copy.", ELL_WARNING);
|
||||
}
|
||||
|
||||
bool result=true;
|
||||
// unlock
|
||||
if (FAILED(upperSurface->UnlockRect()))
|
||||
result=false;
|
||||
if (FAILED(lowerSurface->UnlockRect()))
|
||||
result=false;
|
||||
|
||||
// release
|
||||
upperSurface->Release();
|
||||
lowerSurface->Release();
|
||||
|
||||
if (!result || (upperDesc.Width <= 3 && upperDesc.Height <= 3))
|
||||
return result; // stop generating levels
|
||||
|
||||
// generate next level
|
||||
return createMipMaps(level+1);
|
||||
}
|
||||
|
||||
|
||||
//! creates the hardware texture
|
||||
bool CD3D9Texture::createTexture(u32 flags, IImage * image)
|
||||
{
|
||||
ImageSize = image->getDimension();
|
||||
|
||||
core::dimension2d<u32> optSize = ImageSize.getOptimalSize(!Driver->queryFeature(EVDF_TEXTURE_NPOT), !Driver->queryFeature(EVDF_TEXTURE_NSQUARE), true, Driver->Caps.MaxTextureWidth);
|
||||
|
||||
D3DFORMAT format = D3DFMT_A1R5G5B5;
|
||||
|
||||
switch(getTextureFormatFromFlags(flags))
|
||||
{
|
||||
case ETCF_ALWAYS_16_BIT:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
case ETCF_ALWAYS_32_BIT:
|
||||
format = D3DFMT_A8R8G8B8; break;
|
||||
case ETCF_OPTIMIZED_FOR_QUALITY:
|
||||
{
|
||||
switch(image->getColorFormat())
|
||||
{
|
||||
case ECF_R8G8B8:
|
||||
case ECF_A8R8G8B8:
|
||||
format = D3DFMT_A8R8G8B8; break;
|
||||
case ECF_A1R5G5B5:
|
||||
case ECF_R5G6B5:
|
||||
format = D3DFMT_A1R5G5B5; break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ETCF_OPTIMIZED_FOR_SPEED:
|
||||
format = D3DFMT_A1R5G5B5;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (Driver->getTextureCreationFlag(video::ETCF_NO_ALPHA_CHANNEL))
|
||||
{
|
||||
if (format == D3DFMT_A8R8G8B8)
|
||||
format = D3DFMT_R8G8B8;
|
||||
else if (format == D3DFMT_A1R5G5B5)
|
||||
format = D3DFMT_R5G6B5;
|
||||
}
|
||||
|
||||
const bool mipmaps = Driver->getTextureCreationFlag(video::ETCF_CREATE_MIP_MAPS);
|
||||
|
||||
DWORD usage = 0;
|
||||
|
||||
// This enables hardware mip map generation.
|
||||
if (mipmaps && Driver->queryFeature(EVDF_MIP_MAP_AUTO_UPDATE))
|
||||
{
|
||||
LPDIRECT3D9 intf = Driver->getExposedVideoData().D3D9.D3D9;
|
||||
D3DDISPLAYMODE d3ddm;
|
||||
intf->GetAdapterDisplayMode(Driver->Params.DisplayAdapter, &d3ddm);
|
||||
|
||||
if (D3D_OK==intf->CheckDeviceFormat(Driver->Params.DisplayAdapter,D3DDEVTYPE_HAL,d3ddm.Format,D3DUSAGE_AUTOGENMIPMAP,D3DRTYPE_TEXTURE,format))
|
||||
{
|
||||
usage = D3DUSAGE_AUTOGENMIPMAP;
|
||||
HardwareMipMaps = true;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT hr = Device->CreateTexture(optSize.Width, optSize.Height,
|
||||
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
|
||||
usage, // usage
|
||||
format, D3DPOOL_MANAGED , &Texture, NULL);
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
// try brute force 16 bit
|
||||
HardwareMipMaps = false;
|
||||
if (format == D3DFMT_A8R8G8B8)
|
||||
format = D3DFMT_A1R5G5B5;
|
||||
else if (format == D3DFMT_R8G8B8)
|
||||
format = D3DFMT_R5G6B5;
|
||||
else
|
||||
return false;
|
||||
|
||||
hr = Device->CreateTexture(optSize.Width, optSize.Height,
|
||||
mipmaps ? 0 : 1, // number of mipmaplevels (0 = automatic all)
|
||||
0, format, D3DPOOL_MANAGED, &Texture, NULL);
|
||||
}
|
||||
|
||||
ColorFormat = Driver->getColorFormatFromD3DFormat(format);
|
||||
setPitch(format);
|
||||
return (SUCCEEDED(hr));
|
||||
}
|
||||
|
||||
|
||||
//! copies the image to the texture
|
||||
bool CD3D9Texture::copyTexture(IImage * image)
|
||||
{
|
||||
if (Texture && image)
|
||||
{
|
||||
D3DSURFACE_DESC desc;
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
|
||||
TextureSize.Width = desc.Width;
|
||||
TextureSize.Height = desc.Height;
|
||||
|
||||
D3DLOCKED_RECT rect;
|
||||
HRESULT hr = Texture->LockRect(0, &rect, 0, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Texture data not copied", "Could not LockRect D3D9 Texture.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
|
||||
Pitch = rect.Pitch;
|
||||
image->copyToScaling(rect.pBits, TextureSize.Width, TextureSize.Height, ColorFormat, Pitch);
|
||||
|
||||
hr = Texture->UnlockRect(0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Texture data not copied", "Could not UnlockRect D3D9 Texture.", ELL_ERROR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//! lock function
|
||||
void* CD3D9Texture::lock(E_TEXTURE_LOCK_MODE mode, u32 mipmapLevel)
|
||||
{
|
||||
if (!Texture)
|
||||
return 0;
|
||||
|
||||
MipLevelLocked=mipmapLevel;
|
||||
HRESULT hr;
|
||||
D3DLOCKED_RECT rect;
|
||||
if(!IsRenderTarget)
|
||||
{
|
||||
hr = Texture->LockRect(mipmapLevel, &rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!RTTSurface)
|
||||
{
|
||||
// Make RTT surface large enough for all miplevels (including 0)
|
||||
D3DSURFACE_DESC desc;
|
||||
Texture->GetLevelDesc(0, &desc);
|
||||
hr = Device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format, D3DPOOL_SYSTEMMEM, &RTTSurface, 0);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Offscreen surface creation failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
IDirect3DSurface9 *surface = 0;
|
||||
hr = Texture->GetSurfaceLevel(mipmapLevel, &surface);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Could not get surface.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = Device->GetRenderTargetData(surface, RTTSurface);
|
||||
surface->Release();
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "Data copy failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
hr = RTTSurface->LockRect(&rect, 0, (mode==ETLM_READ_ONLY)?D3DLOCK_READONLY:0);
|
||||
if(FAILED(hr))
|
||||
{
|
||||
os::Printer::log("Could not lock DIRECT3D9 Texture", "LockRect failed.", ELL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return rect.pBits;
|
||||
}
|
||||
|
||||
|
||||
//! unlock function
|
||||
void CD3D9Texture::unlock()
|
||||
{
|
||||
if (!Texture)
|
||||
return;
|
||||
|
||||
if (!IsRenderTarget)
|
||||
Texture->UnlockRect(MipLevelLocked);
|
||||
else if (RTTSurface)
|
||||
RTTSurface->UnlockRect();
|
||||
}
|
||||
|
||||
|
||||
//! Returns original size of the texture.
|
||||
const core::dimension2d<u32>& CD3D9Texture::getOriginalSize() const
|
||||
{
|
||||
return ImageSize;
|
||||
}
|
||||
|
||||
|
||||
//! Returns (=size) of the texture.
|
||||
const core::dimension2d<u32>& CD3D9Texture::getSize() const
|
||||
{
|
||||
return TextureSize;
|
||||
}
|
||||
|
||||
|
||||
//! returns driver type of texture (=the driver, who created the texture)
|
||||
E_DRIVER_TYPE CD3D9Texture::getDriverType() const
|
||||
{
|
||||
return EDT_DIRECT3D9;
|
||||
}
|
||||
|
||||
|
||||
//! returns color format of texture
|
||||
ECOLOR_FORMAT CD3D9Texture::getColorFormat() const
|
||||
{
|
||||
return ColorFormat;
|
||||
}
|
||||
|
||||
|
||||
//! returns pitch of texture (in bytes)
|
||||
u32 CD3D9Texture::getPitch() const
|
||||
{
|
||||
return Pitch;
|
||||
}
|
||||
|
||||
|
||||
//! returns the DIRECT3D9 Texture
|
||||
IDirect3DBaseTexture9* CD3D9Texture::getDX9Texture() const
|
||||
{
|
||||
return Texture;
|
||||
}
|
||||
|
||||
|
||||
//! returns if texture has mipmap levels
|
||||
bool CD3D9Texture::hasMipMaps() const
|
||||
{
|
||||
return HasMipMaps;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
u32 a=0, r=0, g=0, b=0;
|
||||
|
||||
for (s32 dy=0; dy<2; ++dy)
|
||||
{
|
||||
const s32 tgy = (y*2)+dy;
|
||||
for (s32 dx=0; dx<2; ++dx)
|
||||
{
|
||||
const s32 tgx = (x*2)+dx;
|
||||
|
||||
SColor c;
|
||||
if (ColorFormat == ECF_A1R5G5B5)
|
||||
c = A1R5G5B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
|
||||
else
|
||||
c = R5G6B5toA8R8G8B8(*(u16*)(&src[(tgx*2)+(tgy*pitchsrc)]));
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
u16 c;
|
||||
if (ColorFormat == ECF_A1R5G5B5)
|
||||
c = RGBA16(r,g,b,a);
|
||||
else
|
||||
c = A8R8G8B8toR5G6B5(SColor(a,r,g,b).color);
|
||||
*(u16*)(&tgt[(x*2)+(y*pitchtgt)]) = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height,
|
||||
s32 pitchsrc, s32 pitchtgt) const
|
||||
{
|
||||
for (s32 y=0; y<height; ++y)
|
||||
{
|
||||
for (s32 x=0; x<width; ++x)
|
||||
{
|
||||
u32 a=0, r=0, g=0, b=0;
|
||||
SColor c;
|
||||
|
||||
for (s32 dy=0; dy<2; ++dy)
|
||||
{
|
||||
const s32 tgy = (y*2)+dy;
|
||||
for (s32 dx=0; dx<2; ++dx)
|
||||
{
|
||||
const s32 tgx = (x*2)+dx;
|
||||
|
||||
c = *(u32*)(&src[(tgx*4)+(tgy*pitchsrc)]);
|
||||
|
||||
a += c.getAlpha();
|
||||
r += c.getRed();
|
||||
g += c.getGreen();
|
||||
b += c.getBlue();
|
||||
}
|
||||
}
|
||||
|
||||
a /= 4;
|
||||
r /= 4;
|
||||
g /= 4;
|
||||
b /= 4;
|
||||
|
||||
c.set(a, r, g, b);
|
||||
*(u32*)(&tgt[(x*4)+(y*pitchtgt)]) = c.color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
void CD3D9Texture::regenerateMipMapLevels(void* mipmapData)
|
||||
{
|
||||
if (mipmapData)
|
||||
{
|
||||
core::dimension2du size = TextureSize;
|
||||
u32 level=0;
|
||||
do
|
||||
{
|
||||
if (size.Width>1)
|
||||
size.Width /=2;
|
||||
if (size.Height>1)
|
||||
size.Height /=2;
|
||||
++level;
|
||||
IDirect3DSurface9* mipSurface = 0;
|
||||
HRESULT hr = Texture->GetSurfaceLevel(level, &mipSurface);
|
||||
if (FAILED(hr) || !mipSurface)
|
||||
{
|
||||
os::Printer::log("Could not get mipmap level", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
D3DSURFACE_DESC mipDesc;
|
||||
mipSurface->GetDesc(&mipDesc);
|
||||
D3DLOCKED_RECT miplr;
|
||||
|
||||
// lock mipmap surface
|
||||
if (FAILED(mipSurface->LockRect(&miplr, NULL, 0)))
|
||||
{
|
||||
mipSurface->Release();
|
||||
os::Printer::log("Could not lock texture", ELL_WARNING);
|
||||
return;
|
||||
}
|
||||
|
||||
memcpy(miplr.pBits, mipmapData, size.getArea()*getPitch()/TextureSize.Width);
|
||||
mipmapData = (u8*)mipmapData+size.getArea()*getPitch()/TextureSize.Width;
|
||||
// unlock
|
||||
mipSurface->UnlockRect();
|
||||
// release
|
||||
mipSurface->Release();
|
||||
} while (size.Width != 1 || size.Height != 1);
|
||||
}
|
||||
else if (HasMipMaps)
|
||||
{
|
||||
// create mip maps.
|
||||
#ifdef _IRR_USE_D3DXFilterTexture_
|
||||
// The D3DXFilterTexture function seems to get linked wrong when
|
||||
// compiling with both D3D8 and 9, causing it not to work in the D3D9 device.
|
||||
// So mipmapgeneration is replaced with my own bad generation
|
||||
HRESULT hr = D3DXFilterTexture(Texture, NULL, D3DX_DEFAULT, D3DX_DEFAULT);
|
||||
if (FAILED(hr))
|
||||
#endif
|
||||
createMipMaps();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//! returns if it is a render target
|
||||
bool CD3D9Texture::isRenderTarget() const
|
||||
{
|
||||
return IsRenderTarget;
|
||||
}
|
||||
|
||||
|
||||
//! Returns pointer to the render target surface
|
||||
IDirect3DSurface9* CD3D9Texture::getRenderTargetSurface()
|
||||
{
|
||||
if (!IsRenderTarget)
|
||||
return 0;
|
||||
|
||||
IDirect3DSurface9 *pRTTSurface = 0;
|
||||
if (Texture)
|
||||
Texture->GetSurfaceLevel(0, &pRTTSurface);
|
||||
|
||||
if (pRTTSurface)
|
||||
pRTTSurface->Release();
|
||||
|
||||
return pRTTSurface;
|
||||
}
|
||||
|
||||
|
||||
void CD3D9Texture::setPitch(D3DFORMAT d3dformat)
|
||||
{
|
||||
switch(d3dformat)
|
||||
{
|
||||
case D3DFMT_X1R5G5B5:
|
||||
case D3DFMT_A1R5G5B5:
|
||||
Pitch = TextureSize.Width * 2;
|
||||
break;
|
||||
case D3DFMT_A8B8G8R8:
|
||||
case D3DFMT_A8R8G8B8:
|
||||
case D3DFMT_X8R8G8B8:
|
||||
Pitch = TextureSize.Width * 4;
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
Pitch = TextureSize.Width * 2;
|
||||
break;
|
||||
case D3DFMT_R8G8B8:
|
||||
Pitch = TextureSize.Width * 3;
|
||||
break;
|
||||
default:
|
||||
Pitch = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
@ -1,132 +0,0 @@
|
||||
// Copyright (C) 2002-2012 Nikolaus Gebhardt
|
||||
// This file is part of the "Irrlicht Engine".
|
||||
// For conditions of distribution and use, see copyright notice in irrlicht.h
|
||||
|
||||
#ifndef __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
#define __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
|
||||
#include "IrrCompileConfig.h"
|
||||
#ifdef _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#include "ITexture.h"
|
||||
#include "IImage.h"
|
||||
#if defined(__BORLANDC__) || defined (__BCPLUSPLUS__)
|
||||
#include "irrMath.h" // needed by borland for sqrtf define
|
||||
#endif
|
||||
#include <d3d9.h>
|
||||
|
||||
namespace irr
|
||||
{
|
||||
namespace video
|
||||
{
|
||||
|
||||
class CD3D9Driver;
|
||||
// forward declaration for RTT depth buffer handling
|
||||
struct SDepthSurface;
|
||||
/*!
|
||||
interface for a Video Driver dependent Texture.
|
||||
*/
|
||||
class CD3D9Texture : public ITexture
|
||||
{
|
||||
public:
|
||||
|
||||
//! constructor
|
||||
CD3D9Texture(IImage* image, CD3D9Driver* driver,
|
||||
u32 flags, const io::path& name, void* mipmapData=0);
|
||||
|
||||
//! rendertarget constructor
|
||||
CD3D9Texture(CD3D9Driver* driver, const core::dimension2d<u32>& size, const io::path& name,
|
||||
const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
//! destructor
|
||||
virtual ~CD3D9Texture();
|
||||
|
||||
//! lock function
|
||||
virtual void* lock(E_TEXTURE_LOCK_MODE mode=ETLM_READ_WRITE, u32 mipmapLevel=0);
|
||||
|
||||
//! unlock function
|
||||
virtual void unlock();
|
||||
|
||||
//! Returns original size of the texture.
|
||||
virtual const core::dimension2d<u32>& getOriginalSize() const;
|
||||
|
||||
//! Returns (=size) of the texture.
|
||||
virtual const core::dimension2d<u32>& getSize() const;
|
||||
|
||||
//! returns driver type of texture (=the driver, who created the texture)
|
||||
virtual E_DRIVER_TYPE getDriverType() const;
|
||||
|
||||
//! returns color format of texture
|
||||
virtual ECOLOR_FORMAT getColorFormat() const;
|
||||
|
||||
//! returns pitch of texture (in bytes)
|
||||
virtual u32 getPitch() const;
|
||||
|
||||
//! returns the DIRECT3D9 Texture
|
||||
IDirect3DBaseTexture9* getDX9Texture() const;
|
||||
|
||||
//! returns if texture has mipmap levels
|
||||
bool hasMipMaps() const;
|
||||
|
||||
//! Regenerates the mip map levels of the texture. Useful after locking and
|
||||
//! modifying the texture
|
||||
virtual void regenerateMipMapLevels(void* mipmapData=0);
|
||||
|
||||
//! returns if it is a render target
|
||||
virtual bool isRenderTarget() const;
|
||||
|
||||
//! Returns pointer to the render target surface
|
||||
IDirect3DSurface9* getRenderTargetSurface();
|
||||
|
||||
u64 getTextureHandler() const { return (u64)Texture; }
|
||||
|
||||
private:
|
||||
friend class CD3D9Driver;
|
||||
|
||||
void createRenderTarget(const ECOLOR_FORMAT format = ECF_UNKNOWN);
|
||||
|
||||
//! creates the hardware texture
|
||||
bool createTexture(u32 flags, IImage * image);
|
||||
|
||||
//! copies the image to the texture
|
||||
bool copyTexture(IImage * image);
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
bool createMipMaps(u32 level=1);
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
void copy16BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
//! Helper function for mipmap generation.
|
||||
void copy32BitMipMap(char* src, char* tgt,
|
||||
s32 width, s32 height, s32 pitchsrc, s32 pitchtgt) const;
|
||||
|
||||
//! set Pitch based on the d3d format
|
||||
void setPitch(D3DFORMAT d3dformat);
|
||||
|
||||
IDirect3DDevice9* Device;
|
||||
IDirect3DTexture9* Texture;
|
||||
IDirect3DSurface9* RTTSurface;
|
||||
CD3D9Driver* Driver;
|
||||
SDepthSurface* DepthSurface;
|
||||
core::dimension2d<u32> TextureSize;
|
||||
core::dimension2d<u32> ImageSize;
|
||||
s32 Pitch;
|
||||
u32 MipLevelLocked;
|
||||
ECOLOR_FORMAT ColorFormat;
|
||||
|
||||
bool HasMipMaps;
|
||||
bool HardwareMipMaps;
|
||||
bool IsRenderTarget;
|
||||
};
|
||||
|
||||
|
||||
} // end namespace video
|
||||
} // end namespace irr
|
||||
|
||||
#endif // _IRR_COMPILE_WITH_DIRECT3D_9_
|
||||
|
||||
#endif // __C_DIRECTX9_TEXTURE_H_INCLUDED__
|
||||
|
||||
|
@ -723,15 +723,9 @@ namespace UserConfigParams
|
||||
PARAM_DEFAULT( FloatUserConfigParam(3, "font_size",
|
||||
&m_video_group, "The size of fonts. 0 is the smallest and 6 is the biggest") );
|
||||
|
||||
#if defined(_IRR_COMPILE_WITH_DIRECT3D_9_) && defined(_M_ARM)
|
||||
PARAM_PREFIX StringUserConfigParam m_render_driver
|
||||
PARAM_DEFAULT( StringUserConfigParam("directx9", "render_driver",
|
||||
&m_video_group, "Render video driver to use, at the moment gl, vulkan or directx9 is supported.") );
|
||||
#else
|
||||
PARAM_PREFIX StringUserConfigParam m_render_driver
|
||||
PARAM_DEFAULT( StringUserConfigParam("gl", "render_driver",
|
||||
&m_video_group, "Render video driver to use, at the moment gl, vulkan or directx9 is supported.") );
|
||||
#endif
|
||||
&m_video_group, "Render video driver to use, at the moment gl or vulkan are supported.") );
|
||||
|
||||
#if defined(MOBILE_STK)
|
||||
PARAM_PREFIX BoolUserConfigParam m_vulkan_fullscreen_desktop
|
||||
|
@ -500,10 +500,6 @@ begin:
|
||||
driver_created = video::EDT_OPENGL;
|
||||
#endif
|
||||
}
|
||||
else if (std::string(UserConfigParams::m_render_driver) == "directx9")
|
||||
{
|
||||
driver_created = video::EDT_DIRECT3D9;
|
||||
}
|
||||
else if (std::string(UserConfigParams::m_render_driver) == "vulkan")
|
||||
{
|
||||
driver_created = video::EDT_VULKAN;
|
||||
|
@ -687,7 +687,7 @@ void cmdLineHelp()
|
||||
" Takes precedence over trilinear or bilinear\n"
|
||||
" texture filtering.\n"
|
||||
" --shadows=n Set resolution of shadows (0 to disable).\n"
|
||||
" --render-driver=n Render driver to use (gl or directx9).\n"
|
||||
" --render-driver=n Render driver to use (gl or vulkan).\n"
|
||||
" --disable-addon-karts Disable loading of addon karts.\n"
|
||||
" --disable-addon-tracks Disable loading of addon tracks.\n"
|
||||
" --dump-official-karts Dump official karts for current stk-assets.\n"
|
||||
|
Loading…
Reference in New Issue
Block a user