#include <stdio.h>
#include <iostream>
#include "D3DViewportRenderer.h"
#include <maya/MGlobal.h>
#include <maya/MString.h>
#include <maya/MRenderingInfo.h>
#include <maya/MRenderTarget.h>
#include <maya/MFnCamera.h>
#include <maya/MAngle.h>
#include <maya/MPoint.h>
#include <maya/MVector.h>
#include <maya/MItDag.h>
#include <maya/MMatrix.h>
#include <maya/MDagPath.h>
#include <maya/MFnDagNode.h>
#include <maya/MFnMesh.h>
#include <maya/MItMeshPolygon.h>
#include <maya/MBoundingBox.h>
#include <maya/MImage.h>
#include <maya/MDrawTraversal.h>
#include <maya/MGeometryManager.h>
#include <maya/MGeometry.h>
#include <maya/MGeometryData.h>
#include <maya/MGeometryPrimitive.h>
#include <maya/MNodeMessage.h>
#include <maya/MPlug.h>
#include <maya/MPlugArray.h>
#include <maya/MFnSet.h>
#include <maya/MFnNumericData.h>
#include <maya/MItDependencyGraph.h>
#include <maya/MMatrix.h>
#include <stdio.h>
#include <maya/MFnLight.h>
#include <maya/MFnSpotLight.h>
#include <maya/MPxHardwareShader.h>
#include <maya/MRenderProfile.h>
#include <windows.h>
#if defined(D3D9_SUPPORTED)
struct ScreenSpaceVertex
{
D3DXVECTOR4 position;
D3DXVECTOR2 texCoord;
static const DWORD FVF;
};
const DWORD ScreenSpaceVertex::FVF = D3DFVF_XYZRHW | D3DFVF_TEX1;
#endif
D3DViewportRenderer::D3DViewportRenderer()
{
fUIName.set( "Direct3D Renderer");
m_Version = 9.0f;
m_renderWidth = 640;
m_renderHeight = 480;
#if defined(D3D9_SUPPORTED)
m_hWnd = 0;
m_pD3D = 0;
m_pD3DDevice = 0;
m_pTextureOutput = 0;
m_pTextureOutputSurface = 0;
m_readBackBuffer.create(m_renderWidth, m_renderHeight, 4);
m_readBackBuffer.setRGBA( false );
m_pBoundsBuffer = 0;
m_pGeometry = 0;
m_wantFloatingPointTargets = false;
m_pTextureInterm = 0;
m_pTextureIntermSurface = 0;
m_pTexturePost = 0;
m_pDepthStencilSurface = 0;
m_SystemMemorySurface = 0;
m_requireDepthStencilReadback = false;
#endif
}
D3DViewportRenderer::~D3DViewportRenderer()
{
uninitialize();
}
LRESULT CALLBACK D3DWindowProc( HWND hWnd,
UINT msg,
WPARAM wParam,
LPARAM lParam )
{
switch( msg )
{
case WM_CLOSE:
{
}
break;
case WM_DESTROY:
{
}
break;
default:
{
return DefWindowProc( hWnd, msg, wParam, lParam );
}
break;
}
return 0;
}
#if defined(D3D9_SUPPORTED)
bool
D3DViewportRenderer::buildRenderTargets(unsigned int width, unsigned int height)
{
HRESULT hr = -1;
if (width == m_renderWidth &&
height == m_renderHeight &&
m_pTextureInterm &&
m_pTextureOutput &&
m_pTexturePost)
{
return true;
}
m_renderWidth = width;
m_renderHeight = height;
if (m_pTextureInterm)
{
m_pTextureInterm->Release();
m_pTextureInterm = NULL;
}
if (m_pTextureIntermSurface)
{
m_pTextureIntermSurface->Release();
m_pTextureIntermSurface = NULL;
}
if (!m_pTextureInterm)
{
hr = D3DXCreateTexture( m_pD3DDevice,
m_renderWidth,
m_renderHeight,
1,
D3DUSAGE_RENDERTARGET,
m_intermediateTargetFormat,
D3DPOOL_DEFAULT,
&m_pTextureInterm );
m_intermediateTargetFormat = m_outputTargetFormat;
if ( FAILED(hr) )
{
hr = D3DXCreateTexture( m_pD3DDevice,
m_renderWidth,
m_renderHeight,
1,
D3DUSAGE_RENDERTARGET,
m_intermediateTargetFormat,
D3DPOOL_DEFAULT,
&m_pTextureInterm );
}
if ( FAILED(hr) )
{
return false;
}
}
if (m_pTextureInterm)
{
hr = m_pTextureInterm->GetSurfaceLevel( 0, &m_pTextureIntermSurface );
}
if ( FAILED(hr) )
{
return false;
}
if (m_wantFloatingPointTargets)
{
if (m_pTextureOutput)
{
m_pTextureOutput->Release();
m_pTextureOutput = NULL;
}
if (m_pTextureOutputSurface)
{
m_pTextureOutputSurface->Release();
m_pTextureOutputSurface = NULL;
}
if (!m_pTextureOutput)
{
hr = D3DXCreateTexture( m_pD3DDevice,
m_renderWidth,
m_renderHeight,
1,
D3DUSAGE_RENDERTARGET,
m_outputTargetFormat,
D3DPOOL_DEFAULT,
&m_pTextureOutput );
if ( FAILED(hr) )
{
return false;
}
}
if (m_pTextureOutput)
{
hr = m_pTextureOutput->GetSurfaceLevel( 0, &m_pTextureOutputSurface );
}
if ( FAILED(hr) )
{
return false;
}
}
else
{
m_pTextureOutput = m_pTextureInterm;
m_pTextureOutputSurface = m_pTextureIntermSurface;
}
if (m_pTexturePost)
{
m_pTexturePost->Release();
m_pTexturePost = NULL;
}
if (!m_pTexturePost)
{
hr = D3DXCreateTexture( m_pD3DDevice,
m_renderWidth,
m_renderHeight,
1,
D3DUSAGE_RENDERTARGET,
m_intermediateTargetFormat,
D3DPOOL_DEFAULT,
&m_pTexturePost );
if ( FAILED(hr) )
{
return false;
}
}
if (m_SystemMemorySurface)
{
m_SystemMemorySurface->Release();
m_SystemMemorySurface = 0;
}
if (!m_SystemMemorySurface)
{
hr = m_pD3DDevice->CreateOffscreenPlainSurface( m_renderWidth,
m_renderHeight, m_outputTargetFormat, D3DPOOL_SYSTEMMEM,
&m_SystemMemorySurface, NULL );
if (FAILED(hr))
{
return false;
}
}
return (m_pTextureOutput && m_pTextureOutputSurface && m_pTextureInterm &&
m_pTextureIntermSurface && m_pTexturePost && m_SystemMemorySurface);
#if defined(DEPTH_REQUIRED)
if (m_pDepthStencilSurface)
{
m_pDepthStencilSurface->Release();
m_pDepthStencilSurface = 0;
}
if (m_requireDepthStencilReadback && !m_pDepthStencilSurface)
{
hr = m_pD3DDevice->CreateDepthStencilSurface(
m_renderWidth, m_renderHeight, m_depthStencilFormat, D3DMULTISAMPLE_NONE,
0, FALSE,
&m_pDepthStencilSurface, NULL );
if (FAILED(hr))
{
MGlobal::displayWarning(
"Direct3D renderer : Failed to create depth/stencil surface. Depth read back will not be available.");
}
}
#endif
}
#endif
D3DViewportRenderer::initialize()
{
#if defined(D3D9_SUPPORTED)
MString wantFloatingPoint(
"D3D_RENDERER_FLOAT_TARGETS");
int value;
{
m_wantFloatingPointTargets = true;
}
else
{
m_wantFloatingPointTargets = (value != 0);
}
m_wantFloatingPointTargets = false;
if (!m_hWnd)
{
WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, (WNDPROC) D3DWindowProc, 0L, 0L,
GetModuleHandle(NULL), NULL, NULL, NULL, NULL,
"D3D Viewport Renderer", NULL };
if (RegisterClassEx( &wc ))
{
m_hWnd = CreateWindow( "D3D Viewport Renderer", "D3D Viewport Renderer",
WS_OVERLAPPEDWINDOW, 0, 0, m_renderWidth, m_renderHeight,
NULL, NULL, wc.hInstance, NULL );
}
}
if (m_hWnd)
{
if (!m_pD3D)
m_pD3D = Direct3DCreate9( D3D_SDK_VERSION );
}
HRESULT hr;
if (m_wantFloatingPointTargets)
{
m_intermediateTargetFormat = D3DFMT_A16B16G16R16F;
}
else
{
m_intermediateTargetFormat = D3DFMT_A8R8G8B8;
}
m_outputTargetFormat = D3DFMT_A8R8G8B8;
if (m_requireDepthStencilReadback)
{
m_depthStencilFormat = D3DFMT_D32;
}
else
m_depthStencilFormat = D3DFMT_D24S8;
if (m_pD3D)
{
if (!m_pD3DDevice)
{
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory( &d3dpp, sizeof(d3dpp) );
d3dpp.BackBufferFormat = m_outputTargetFormat;
d3dpp.Windowed = TRUE;
d3dpp.BackBufferWidth = 1920;
d3dpp.BackBufferHeight = 1680;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.EnableAutoDepthStencil = TRUE;
d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
hr = m_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
&d3dpp, &m_pD3DDevice );
if (FAILED(hr))
{
hr = m_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, m_hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
&d3dpp, &m_pD3DDevice );
}
if ( FAILED(hr) )
m_pD3DDevice = 0;
}
}
if (m_pD3DDevice)
{
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
bool builtRenderTargets = buildRenderTargets(640, 480);
if (builtRenderTargets)
{
bool loaded = m_resourceManager.initializePostEffects( shaderLocation, m_pD3DDevice );
const MString defaultSurfaceEffect(
"Maya_fixedFunction");
loaded = m_resourceManager.initializeDefaultSurfaceEffect( shaderLocation, m_pD3DDevice, defaultSurfaceEffect);
if (m_hWnd && m_pD3D && m_pD3DDevice && m_pTextureOutput && m_pTextureOutputSurface &&
m_pTextureInterm && m_pTextureIntermSurface )
{
}
}
}
{
uninitialize();
}
#else
#endif
return status;
}
D3DViewportRenderer::uninitialize()
{
#if defined(D3D9_SUPPORTED)
if ( m_pTextureOutput )
{
if (m_pTextureOutput != m_pTextureInterm)
m_pTextureOutput->Release();
m_pTextureOutput = 0;
}
if ( m_pTextureOutputSurface )
{
if (m_pTextureOutputSurface != m_pTextureIntermSurface)
m_pTextureOutputSurface->Release();
m_pTextureOutputSurface = 0;
}
if ( m_pTextureInterm )
{
m_pTextureInterm->Release();
m_pTextureInterm = 0;
}
if ( m_pTextureIntermSurface )
{
m_pTextureIntermSurface->Release();
m_pTextureIntermSurface = 0;
}
if ( m_pTexturePost )
{
m_pTexturePost->Release();
m_pTexturePost = 0;
}
if ( m_SystemMemorySurface )
{
m_SystemMemorySurface->Release();
m_SystemMemorySurface = 0;
}
if (m_pDepthStencilSurface)
{
m_pDepthStencilSurface->Release();
m_pDepthStencilSurface = 0;
}
if ( m_pBoundsBuffer != NULL )
{
m_pBoundsBuffer->Release();
m_pBoundsBuffer = 0;
}
if (m_pGeometry)
{
m_pGeometry->Release();
m_pGeometry = 0;
}
m_resourceManager.clearResources(false, true);
if ( m_pD3DDevice )
{
m_pD3DDevice->Release();
m_pD3DDevice = 0;
}
if ( m_pD3D )
{
m_pD3D->Release();
m_pD3D = 0;
}
if (m_hWnd)
{
ReleaseDC( m_hWnd, GetDC(m_hWnd ));
DestroyWindow(m_hWnd);
UnregisterClass("D3D Viewport Renderer", GetModuleHandle(NULL));
m_hWnd = 0;
}
#endif
}
{
#if defined(D3D9_SUPPORTED)
unsigned int currentWidth = target.
width();
unsigned int currentHeight = target.
height();
if (!buildRenderTargets(currentWidth, currentHeight))
#endif
#if defined(D3D9_SUPPORTED)
if ( m_resourceManager.translateCamera( cameraPath ) )
{
if ( renderToTarget( renderInfo ) )
{
if ( requireReadBack )
{
if (readFromTargetToSystemMemory())
{
{
unsigned int targetW = target.
width();
unsigned int targetH = target.
height();
unsigned int m_readBackBufferWidth, m_readBackBufferHeight;
m_readBackBuffer.getSize(m_readBackBufferWidth, m_readBackBufferHeight);
if (m_readBackBufferWidth && m_readBackBufferHeight)
{
if (m_readBackBufferWidth > targetW ||
m_readBackBufferHeight > targetH)
{
m_readBackBuffer.resize(targetW, targetH);
}
else
{
(short)(targetW/2 - m_readBackBufferWidth/2),
(short)(targetH/2 - m_readBackBufferHeight/2));
}
}
}
else
{
}
}
else
}
else
{
}
}
else
}
else
{
}
#else
#endif
return status;
}
bool
float version )
{
return ((api == m_API) && (version == m_Version) );
}
bool
{
return (override == fRenderingOverride);
}
#if defined(D3D9_SUPPORTED)
bool
D3DViewportRenderer::translateCamera(
const MRenderingInfo &renderInfo )
{
return m_resourceManager.translateCamera( cameraPath );
else
return false;
}
bool D3DViewportRenderer::drawCube(float minVal[3], float maxVal[3], bool filled, bool useDummyGeometry,
float color[3], LPDIRECT3DVERTEXBUFFER9 buffer )
{
if (!m_pD3DDevice)
return false;
D3DMATERIAL9 Material;
Material.Emissive.r = color[0];
Material.Emissive.g = color[1];
Material.Emissive.b = color[2];
Material.Emissive.a = 1.0f;
Material.Ambient.r = color[0];
Material.Ambient.g = color[1];
Material.Ambient.b = color[2];
Material.Ambient.a = 1.0f;
m_pD3DDevice->SetMaterial( &Material);
m_pD3DDevice->LightEnable( 0, false);
m_pD3DDevice->LightEnable( 1, false);
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
if (!filled)
{
m_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
}
else
{
m_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
}
m_pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
m_pD3DDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
if (!m_pGeometry)
{
if (useDummyGeometry)
{
}
}
if (useDummyGeometry && m_pGeometry)
{
m_pGeometry->DrawSubset(0);
return true;
}
LPDIRECT3DVERTEXBUFFER9 bufferToFill = m_pBoundsBuffer;
if (!bufferToFill)
{
m_pD3DDevice->CreateVertexBuffer( 24*sizeof(PlainVertex),0, PlainVertex::FVF_Flags,
D3DPOOL_DEFAULT, &bufferToFill, NULL );
}
if (!bufferToFill)
{
return false;
}
PlainVertex cube[] =
{
{ minVal[0], maxVal[1], minVal[2]},
{ maxVal[0], maxVal[1], minVal[2]},
{ minVal[0], minVal[1], minVal[2] },
{ maxVal[0], minVal[1], minVal[2] },
{minVal[0], maxVal[1], maxVal[2] },
{minVal[0],minVal[1], maxVal[2] },
{ maxVal[0], maxVal[1], maxVal[2] },
{ maxVal[0],minVal[1], maxVal[2] },
{minVal[0], maxVal[1], maxVal[2] },
{ maxVal[0], maxVal[1], maxVal[2] },
{minVal[0], maxVal[1],minVal[2] },
{ maxVal[0], maxVal[1],minVal[2] },
{minVal[0],minVal[1], maxVal[2] },
{minVal[0],minVal[1],minVal[2] },
{ maxVal[0],minVal[1], maxVal[2] },
{ maxVal[0],minVal[1],minVal[2] },
{ maxVal[0], maxVal[1],minVal[2] },
{ maxVal[0], maxVal[1], maxVal[2] },
{ maxVal[0],minVal[1],minVal[2] },
{ maxVal[0],minVal[1], maxVal[2] },
{minVal[0], maxVal[1],minVal[2] },
{minVal[0],minVal[1],minVal[2] },
{minVal[0], maxVal[1], maxVal[2] },
{minVal[0],minVal[1], maxVal[2] }
};
void *pVertices = NULL;
bufferToFill->Lock( 0, sizeof(cube), (void**)&pVertices, 0 );
memcpy( pVertices, cube, sizeof(cube) );
bufferToFill->Unlock();
m_pD3DDevice->SetStreamSource( 0, bufferToFill, 0, sizeof(PlainVertex) );
m_pD3DDevice->SetFVF( PlainVertex::FVF_Flags );
m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );
m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 4, 2 );
m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 8, 2 );
m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 12, 2 );
m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 16, 2 );
m_pD3DDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 20, 2 );
m_pD3DDevice->LightEnable( 0, true);
m_pD3DDevice->LightEnable( 1, true);
return true;
}
void
D3DViewportRenderer::clearResources(bool onlyInvalidItems, bool clearShaders)
{
m_resourceManager.clearResources( onlyInvalidItems, clearShaders );
}
{
MPlug shaderPlug = fnNode.findPlug(
"surfaceShader");
bool asSrc = false;
bool asDst = true;
shaderPlug.
connectedTo( connectedPlugs, asDst, asSrc );
if (connectedPlugs.
length() != 1)
else
return connectedPlugs[0].node();
}
}
bool D3DViewportRenderer::setSurfaceMaterialShader(
const MDagPath &dagPath, D3DGeometry* Geometry,
const D3DXMATRIXA16 &objectToWorld,
const D3DXMATRIXA16 &objectToWorldInvTranspose,
const D3DXMATRIXA16 &worldViewProjection,
const D3DXVECTOR4 &worldEyePosition)
{
if (!Geometry)
return false;
const SurfaceEffectItemList & surfaceEffects = m_resourceManager.getSurfaceEffectItemList();
bool havePixelShader = (surfaceEffects.size() > 0);
if (havePixelShader)
{
SurfaceEffectItem *defaultItem = surfaceEffects.front();
if (defaultItem)
{
ID3DXEffect* effect = defaultItem->fEffect;
if (effect)
{
HRESULT hres = effect->SetTechnique("MayaPhong");
if (hres != D3D_OK)
havePixelShader = false;
else
{
D3DXHANDLE handle;
handle = effect->GetParameterBySemantic( NULL, "WorldView" );
effect->SetMatrix( handle, &objectToWorld );
handle = effect->GetParameterBySemantic( NULL, "WorldViewInverseTranspose" );
effect->SetMatrix( handle, &objectToWorldInvTranspose );
handle = effect->GetParameterBySemantic( NULL, "WorldViewProjection" );
effect->SetMatrix( handle, &worldViewProjection );
for (; !dagIterator.isDone(); dagIterator.next())
{
if ( !dagIterator.getPath(lightPath) )
continue;
MVector direction( 0.0, 0.0, 1.0 );
direction.normalize();
D3DXVECTOR4 e_val((float)direction.x, (float)direction.y, (float)direction.z, 1.0f );
hres = effect->SetVector( "lightDir", &e_val );
MColor colorVal = fnLight.color();
float intensity = fnLight.intensity();
D3DXVECTOR4 c_val( colorVal.
r * intensity, colorVal.
g * intensity, colorVal.
b * intensity, 1.0f );
hres = effect->SetVector( "lightColor", &c_val );
}
bool isTransparent = false;
if (!fnMesh.getConnectedSetsAndMembers(instanceNum, sets, comps, true))
{
MObject shaderNode = findShader(set);
{
float rgb[3];
D3DTexture* Texture = NULL;
{
if( !It.isDone())
{
Texture = m_resourceManager.getTexture( It.thisNode());
hres = effect->SetTexture( "diffuseTexture", Texture->Texture( m_pD3DDevice ));
D3DXVECTOR4 e_val(1.0f, 1.0f, 1.0f, 1.0f );
hres = effect->SetVector( "diffuseMaterial", &e_val);
hres = effect->SetTechnique("MayaPhongTextured");
}
else
{
val.getData( rgb[0], rgb[1], rgb[2]);
D3DXVECTOR4 e_val(rgb[0], rgb[1], rgb[2], 1.0f );
hres = effect->SetVector( "diffuseMaterial", &e_val);
}
}
{
float diff;
}
{
val.getData( rgb[0], rgb[1], rgb[2]);
D3DXVECTOR4 e_val( rgb[0], rgb[1], rgb[2], 1.0f );
effect->SetVector( "ambientMaterial", &e_val );
}
{
val.getData( rgb[0], rgb[1], rgb[2]);
D3DXVECTOR4 e_val( 1.0f - rgb[0], 1.0f - rgb[1], 1.0f - rgb[2], 1.0f );
effect->SetVector( "transparency", &e_val );
if (rgb[0] < 1.0f || rgb[1] < 1.0f || rgb[2] < 1.0f)
isTransparent = true;
}
{
val.getData( rgb[0], rgb[1], rgb[2]);
}
{
val.getData( rgb[0], rgb[1], rgb[2]);
D3DXVECTOR4 e_val( rgb[0], rgb[1], rgb[2], 1.0f );
effect->SetVector( "specularMaterial", &e_val );
}
{
effect->SetFloat( "specularPower", 0.0f );
}
{
{
float cosPower = 0.0f;
hres = effect->SetFloat( "specularPower", cosPower * 4.0f );
}
}
{
{
float eccentricity = 0.0f;
eccentricityPlug.
getValue( eccentricity );
hres = effect->SetFloat( "specularPower", (eccentricity < 0.03125f) ? 128.0f : 4.0f / eccentricity );
}
}
else
{
{
float roughness = 0.0f;
hres = effect->SetFloat( "specularPower", roughness * 4.0f );
}
}
}
}
unsigned int numPasses;
effect->Begin( &numPasses, 0 );
if (hres != D3D_OK)
havePixelShader = false;
else
{
for (unsigned int p=0; p<numPasses; ++p)
{
hres = effect->BeginPass( p );
if (hres == D3D_OK)
{
Geometry->Render( m_pD3DDevice);
}
hres = effect->EndPass();
}
}
hres = effect->End();
if (hres != D3D_OK)
havePixelShader = false;
}
}
}
}
return havePixelShader;
}
bool D3DViewportRenderer::setSurfaceMaterial(
const MDagPath &dagPath )
{
D3DMATERIAL9 Material;
bool isTransparent = false;
if (!fnMesh.getConnectedSetsAndMembers(instanceNum, sets, comps, true))
for (
unsigned i=0; i<sets.
length(); i++ )
{
continue;
}
MObject shaderNode = findShader(set);
{
float rgb[3];
D3DTexture* Texture = NULL;
{
if( !It.isDone())
{
Texture = m_resourceManager.getTexture( It.thisNode());
m_pD3DDevice->SetTexture( 0, Texture->Texture( m_pD3DDevice));
m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE);
m_pD3DDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE);
m_pD3DDevice->SetSamplerState( 0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
m_pD3DDevice->SetSamplerState( 0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
m_pD3DDevice->SetSamplerState( 0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
m_pD3DDevice->SetRenderState(D3DRS_WRAP0, D3DWRAPCOORD_0);
m_pD3DDevice->SetRenderState(D3DRS_WRAP1, D3DWRAPCOORD_1);
Material.Diffuse.r = Material.Diffuse.g = Material.Diffuse.b = Material.Diffuse.a = 1.0f;
}
else
{
m_pD3DDevice->SetTexture( 0, NULL);
val.getData( rgb[0], rgb[1], rgb[2]);
Material.Diffuse.r = (float)rgb[0];
Material.Diffuse.g = (float)rgb[1];
Material.Diffuse.b = (float)rgb[2]; Material.Diffuse.a = 1.0f;
}
}
{
float diff;
Material.Diffuse.r *= (float)diff;
Material.Diffuse.g *= (float)diff;
Material.Diffuse.b *= (float)diff;
}
{
val.getData( rgb[0], rgb[1], rgb[2]);
Material.Ambient.r = (float)rgb[0];
Material.Ambient.g = (float)rgb[1];
Material.Ambient.b = (float)rgb[2]; Material.Ambient.a = 1.0f;
}
{
val.getData( rgb[0], rgb[1], rgb[2]);
Material.Diffuse.a = 1.0f - (rgb[0] + rgb[1] + rgb[2]) / 3.0f;
if (Material.Diffuse.a < 1.0f)
isTransparent = true;
}
{
val.getData( rgb[0], rgb[1], rgb[2]);
Material.Emissive.r = (float)rgb[0];
Material.Emissive.g = (float)rgb[1];
Material.Emissive.b = (float)rgb[2]; Material.Emissive.a = 1.0f;
}
{
val.getData( rgb[0], rgb[1], rgb[2]);
Material.Specular.r = (float)rgb[0];
Material.Specular.g = (float)rgb[1];
Material.Specular.b = (float)rgb[2]; Material.Specular.a = 1.0f;
}
Material.Power = 20.0f;
{
Material.Power = 0.0f;
}
{
{
float cosPower = 0.0f;
Material.Power = cosPower * 4.0f;
}
}
{
{
float eccentricity = 0.0f;
eccentricityPlug.
getValue( eccentricity );
Material.Power = (eccentricity < 0.03125f) ? 128.0f : 4.0f / eccentricity;
}
}
else
{
{
float roughness = 0.0f;
Material.Power = roughness * 4.0f;
}
}
break;
}
}
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, isTransparent);
m_pD3DDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
m_pD3DDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
m_pD3DDevice->SetMaterial( &Material);
return true;
}
bool D3DViewportRenderer::drawSurface(
const MDagPath &dagPath,
bool active,
bool templated)
{
bool drewSurface = false;
{
float color[3] = {0.6f, 0.3f, 0.0f};
if (active)
{
color[0] = 1.0f;
color[1] = 1.0f;
color[2] = 1.0f;
}
else if (templated)
{
color[0] = 1.0f;
color[1] = 0.686f;
color[2] = 0.686f;
}
drawBounds( matrix, box, false, true, color);
return true;
}
{
bool drewWithHwShader = false;
{
if (!fnMesh.getConnectedSetsAndMembers(instanceNum, sets, comps, true))
for (
unsigned i=0; i<sets.
length(); i++ )
{
continue;
}
MObject shaderNode = findShader(set);
{
if (hwShader)
{
{
}
}
}
}
}
D3DGeometry* Geometry = m_resourceManager.getGeometry( dagPath, m_pD3DDevice);
if( Geometry)
{
D3DXMATRIXA16 objectToWorld = D3DXMATRIXA16
(
);
m_pD3DDevice->SetTransform( D3DTS_WORLD, &objectToWorld );
m_pD3DDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
m_pD3DDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_GOURAUD );
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, 0xFFFFFFFF );
m_pD3DDevice->SetRenderState( D3DRS_VERTEXBLEND, FALSE );
m_pD3DDevice->SetRenderState( D3DRS_INDEXEDVERTEXBLENDENABLE, FALSE );
m_pD3DDevice->SetRenderState( D3DRS_COLORWRITEENABLE, 0xFFFFFFFF );
if (!drewWithHwShader)
{
bool drewGeometryWithShader = false;
MString usePixelShader(
"D3D_USE_PIXEL_SHADER");
int val = 0;
{
D3DXMATRIXA16 objectToWorldInvTransp = D3DXMATRIXA16
(
);
eyePos *= mm_currentViewMatrix;
D3DXVECTOR4 worldEye( (float)eyePos[0], (float)eyePos[1], (float)eyePos[2], (float)eyePos[3]);
drewGeometryWithShader = setSurfaceMaterialShader( dagPath, Geometry, objectToWorld, objectToWorldInvTransp,
objectToWorld * m_currentViewMatrix * m_currentProjectionMatrix,
worldEye );
}
if (!drewGeometryWithShader)
{
D3DMATERIAL9 Material;
if (active)
{
m_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
Material.Diffuse.r = 1.0f; Material.Diffuse.g = 1.0f; Material.Diffuse.b = 1.0f; Material.Diffuse.a = 1.0f;
}
else if (templated)
{
m_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
Material.Diffuse.r = 1.0f; Material.Diffuse.g = 0.686f; Material.Diffuse.b = 0.686f; Material.Diffuse.a = 1.0f;
}
else
{
m_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
Material.Diffuse.r = 0.5f; Material.Diffuse.g = 0.5f; Material.Diffuse.b = 0.5f; Material.Diffuse.a = 1.0f;
}
Material.Ambient.r = 0.0f; Material.Ambient.g = 0.0f; Material.Ambient.b = 0.0f; Material.Ambient.a = 0.0f;
Material.Specular.r = 1.0f; Material.Specular.g = 1.0f; Material.Specular.b = 1.0f; Material.Specular.a = 1.0f;
Material.Emissive.r = 0.0f; Material.Emissive.g = 0.0f; Material.Emissive.b = 0.0f; Material.Emissive.a = 0.0f;
Material.Power = 50.0f;
bool scanForMayaMaterial = true;
if (!templated && scanForMayaMaterial)
{
if (!setSurfaceMaterial( dagPath ))
{
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
m_pD3DDevice->SetMaterial( &Material);
}
}
Geometry->Render( m_pD3DDevice);
}
}
m_pD3DDevice->SetTexture( 0, NULL);
m_pD3DDevice->SetRenderState(D3DRS_WRAP0, 0);
m_pD3DDevice->SetRenderState(D3DRS_WRAP1, 0);
if (active)
{
bool drawActiveWithBounds = false;
if (drawActiveWithBounds)
{
float color[3] = {1.0f, 1.0f, 1.0f};
drawBounds( matrix, box, false, false, color );
}
else
{
D3DMATERIAL9 Material;
Material.Emissive.r = 1.0;
Material.Emissive.g = 1.0;
Material.Emissive.b = 1.0;
Material.Emissive.a = 1.0f;
Material.Ambient.r = 1.0;
Material.Ambient.g = 1.0;
Material.Ambient.b = 1.0;
Material.Ambient.a = 1.0f;
m_pD3DDevice->SetMaterial( &Material);
m_resourceManager.enableLights( FALSE, m_pD3DDevice );
m_pD3DDevice->SetRenderState( D3DRS_ANTIALIASEDLINEENABLE, TRUE );
m_pD3DDevice->SetRenderState( D3DRS_SHADEMODE, D3DSHADE_FLAT );
m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false);
m_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_WIREFRAME );
m_pD3DDevice->SetRenderState( D3DRS_SLOPESCALEDEPTHBIAS, 100 );
m_pD3DDevice->SetRenderState( D3DRS_DEPTHBIAS, 10 );
Geometry->Render( m_pD3DDevice);
m_pD3DDevice->SetRenderState( D3DRS_DEPTHBIAS, 0 );
m_pD3DDevice->SetRenderState( D3DRS_SLOPESCALEDEPTHBIAS, 0 );
m_pD3DDevice->SetRenderState( D3DRS_FILLMODE, D3DFILL_SOLID );
m_resourceManager.enableLights( TRUE, m_pD3DDevice );
}
}
}
}
return drewSurface;
}
{
bool useDrawTraversal = true;
float groundPlaneColor[3] = { 0.8f, 0.8f, 0.8f };
if (useDrawTraversal)
{
{
if (!trav)
{
return true;
}
{
return true;
}
unsigned int i;
for (i=0; i<numItems; i++)
{
{
bool drawIt = false;
continue;
bool active = false;
bool templated = false;
{
drawIt = true;
{
active = true;
}
{
templated = true;
}
else
{
;
;
else
;
}
}
{
drawBounds( matrix, box, false, false, groundPlaneColor );
}
if (drawIt)
{
drawSurface( path, active, templated );
}
}
}
if (trav)
delete trav;
bool onlyInvalidItems = true;
clearResources( onlyInvalidItems, false );
}
}
else
{
MItDag dagIterator( traversalType, filter, &status);
for ( ; !dagIterator.isDone(); dagIterator.next() )
{
status = dagIterator.getPath(dagPath);
if ( !status ) {
status.
perror(
"MItDag::getPath");
continue;
}
if ( !status ) {
status.
perror(
"MFnDagNode constructor");
continue;
}
drawBounds( matrix, box, false, false, NULL );
}
}
return true;
}
bool D3DViewportRenderer::drawBounds(
const MMatrix &matrix,
const MBoundingBox &box,
bool filled,
bool useDummyGeometry,
float color[3],
LPDIRECT3DVERTEXBUFFER9 buffer )
{
D3DXMATRIXA16 mat = D3DXMATRIXA16
(
);
m_pD3DDevice->SetTransform( D3DTS_WORLD, &mat );
float minVal[3] = { (float)minPt.
x, (
float)minPt.
y, (float)minPt.
z };
float maxVal[3] = { (float)maxPt.
x, (
float)maxPt.
y, (float)maxPt.
z };
drawCube( minVal, maxVal, filled, useDummyGeometry, color, buffer );
return true;
}
bool D3DViewportRenderer::renderToTarget(
const MRenderingInfo &renderInfo )
{
{
return false;
}
if (!m_pD3DDevice || !m_pTextureOutput || !m_pTextureInterm)
return false;
HRESULT hres;
hres = m_pD3DDevice->SetRenderTarget( 0, m_pTextureIntermSurface );
if (m_requireDepthStencilReadback && m_pDepthStencilSurface)
hres = m_pD3DDevice->SetDepthStencilSurface( m_pDepthStencilSurface );
hres = m_pD3DDevice->BeginScene();
if (hres == D3D_OK)
{
setupMatrices( renderInfo );
hres = m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_COLORVALUE(0.0f,0.0f,0.0f,1.0f), 1.0f, 0 );
m_resourceManager.setupLighting(m_pD3DDevice);
if (hres == D3D_OK)
{
drawScene(renderInfo);
}
m_resourceManager.cleanupLighting(m_pD3DDevice);
}
hres = m_pD3DDevice->EndScene();
if (hres != D3D_OK)
return false;
postRenderToTarget();
return true;
}
{
if (!m_pD3DDevice)
return false;
D3DXMATRIXA16 vm( (
float)view.
matrix[0][0], (
float)view.
matrix[0][1], (
float)view.
matrix[0][2], (
float)view.
matrix[0][3],
D3DXMATRIXA16 pm( (
float)projection.
matrix[0][0], (
float)projection.
matrix[0][1], (
float)projection.
matrix[0][2], (
float)projection.
matrix[0][3],
(
float)projection.
matrix[1][0], (
float)projection.
matrix[1][1], (
float)projection.
matrix[1][2], (
float)projection.
matrix[1][3],
(
float)projection.
matrix[2][0], (
float)projection.
matrix[2][1], (
float)projection.
matrix[2][2], (
float)projection.
matrix[2][3],
(
float)projection.
matrix[3][0], (
float)projection.
matrix[3][1], (
float)projection.
matrix[3][2], (
float)projection.
matrix[3][3]);
m_pD3DDevice->SetTransform( D3DTS_PROJECTION, &pm );
m_pD3DDevice->SetTransform( D3DTS_VIEW, &vm );
return true;
}
void D3DViewportRenderer::drawFullScreenQuad(float leftU, float topV,
float rightU, float bottomV,
float targetWidth, float targetHeight,
LPDIRECT3DDEVICE9 D3D)
{
float width = targetWidth - 0.5f;
float height = targetHeight - 0.5f;
ScreenSpaceVertex screenQuad[4];
screenQuad[0].position = D3DXVECTOR4(-0.5f, -0.5f, 0.5f, 1.0f);
screenQuad[0].texCoord = D3DXVECTOR2(leftU, topV);
screenQuad[1].position = D3DXVECTOR4(width, -0.5f, 0.5f, 1.0f);
screenQuad[1].texCoord = D3DXVECTOR2(rightU, topV);
screenQuad[2].position = D3DXVECTOR4(-0.5f, height, 0.5f, 1.0f);
screenQuad[2].texCoord = D3DXVECTOR2(leftU, bottomV);
screenQuad[3].position = D3DXVECTOR4(width, height, 0.5f, 1.0f);
screenQuad[3].texCoord = D3DXVECTOR2(rightU, bottomV);
D3D->SetRenderState(D3DRS_ZENABLE, FALSE);
D3D->SetFVF(ScreenSpaceVertex::FVF);
D3D->DrawPrimitiveUP(D3DPT_TRIANGLESTRIP, 2, screenQuad, sizeof(ScreenSpaceVertex));
D3D->SetRenderState(D3DRS_ZENABLE, TRUE);
}
bool D3DViewportRenderer::postRenderToTarget()
{
if (!m_pTexturePost)
return false;
IDirect3DSurface9 *postSurface = NULL;
HRESULT hres = m_pTexturePost->GetSurfaceLevel( 0, &postSurface );
if (hres != D3D_OK)
return false;
IDirect3DSurface9 *currentSurface[2] = { m_pTextureIntermSurface, postSurface };
LPDIRECT3DTEXTURE9 currentTexture[2] = { m_pTextureInterm, m_pTexturePost };
unsigned int currentTarget = 0;
unsigned int newTarget = 0;
D3DSURFACE_DESC surfaceDesc;
m_pTextureOutputSurface->GetDesc( &surfaceDesc );
float quad_renderWidth = (float)surfaceDesc.Width;
float quad_renderHeight = (float)surfaceDesc.Height;
unsigned int numEffectsApplied = 0;
const MStringArray &enabledEffects = m_resourceManager.getListOfEnabledPostEffects();
const PostEffectItemList &postEffectList = m_resourceManager.getPostEffectItemList();
unsigned int numOfEnabledEffects = enabledEffects.
length();
unsigned int numEffects = (unsigned int) postEffectList.size();
if (!m_wantFloatingPointTargets && !numOfEnabledEffects || !numEffects)
return false;
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
for (unsigned int m=0; m<numOfEnabledEffects ; m++)
{
ID3DXEffect* effect = NULL;
PostEffectItem *effectItem = NULL;
PostEffectItemList::const_iterator eit, end_eit;
end_eit = postEffectList.end();
for (eit = postEffectList.begin(); eit != end_eit; eit++)
{
PostEffectItem *item = *eit;
if (item)
{
if (enabledEffects[m] == item->fName)
{
effectItem = item;
effect = item->fEffect;
break;
}
}
}
if (effect != NULL)
{
newTarget = ( currentTarget + 1 ) % 2;
m_pD3DDevice->SetRenderTarget( 0, currentSurface[newTarget] );
m_pD3DDevice->BeginScene();
{
hres = effect->SetTechnique( "PostProcess" );
if (hres != D3D_OK)
continue;
effect->SetFloat( "duKernel", 1.0f / (float)quad_renderWidth );
effect->SetFloat( "dvKernel", 1.0f / (float)quad_renderHeight);
if (effectItem->fName ==
MString(
"PostProcess_ToneMapFilter"))
{
double value = 1.0;
MString toneMapExp(
"PostProcess_ToneMapFilter_Exposure");
effect->SetFloat( "exposure", (float)value );
}
else if (effectItem->fName ==
MString(
"PostProcess_SobelFilter"))
{
double value = 20;
MString thickness(
"PostProcess_SobelFilter_edgeThickness");
effect->SetFloat( "edgeThickness", (float)value);
}
unsigned int numPasses;
hres = effect->Begin( &numPasses, 0 );
if (hres != D3D_OK)
continue;
else
{
hres = effect->SetTexture( "textureSourceColor", currentTexture[currentTarget] );
if (hres != D3D_OK)
{
m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET ,
D3DCOLOR_COLORVALUE(1.0f,0.0f,0.0f,1.0f), 1.0f, 0 );
continue;
}
for (unsigned int p=0; p<numPasses; ++p)
{
hres = effect->BeginPass( p );
if (hres != D3D_OK)
{
m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET ,
D3DCOLOR_COLORVALUE(1.0f,0.0f,0.0f,1.0f), 1.0f, 0 );
continue;
}
drawFullScreenQuad( 0.0f, 0.0f, 1.0f, 1.0f,
quad_renderWidth, quad_renderHeight, m_pD3DDevice );
hres = effect->EndPass();
if (hres != D3D_OK)
{
m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET ,
D3DCOLOR_COLORVALUE(1.0f,0.0f,0.0f,1.0f), 1.0f, 0 );
continue;
}
}
}
hres = effect->End();
numEffectsApplied++;
}
m_pD3DDevice->SetTexture( 0, NULL);
m_pD3DDevice->EndScene();
#if defined(_DEBUG_POST_BUFFERS_)
bool dumpToFile= false;
if (dumpToFile)
{
const char fileName[] = "c:\\temp\\d3dDump_newTarget.jpg";
HRESULT hres = D3DXSaveSurfaceToFile( fileName, D3DXIFF_JPG,
currentSurface[newTarget], NULL , NULL );
const char fileName2[] = "c:\\temp\\d3dDump_oldTarget.jpg";
hres = D3DXSaveSurfaceToFile( fileName2, D3DXIFF_JPG,
currentSurface[currentTarget], NULL , NULL );
}
#endif
currentTarget = newTarget;
}
}
if ((currentSurface[currentTarget] != m_pTextureIntermSurface) ||
(m_pTextureOutputSurface != m_pTextureIntermSurface))
{
m_pD3DDevice->SetRenderTarget( 0, m_pTextureOutputSurface );
m_pD3DDevice->BeginScene();
{
m_pD3DDevice->SetTexture( 0, currentTexture[currentTarget] );
drawFullScreenQuad( 0.0f, 0.0f, 1.0f, 1.0f,
quad_renderWidth, quad_renderHeight, m_pD3DDevice );
}
m_pD3DDevice->EndScene();
}
if (postSurface)
postSurface->Release();
m_pD3DDevice->SetRenderState( D3DRS_ZENABLE, TRUE );
return true;
}
bool D3DViewportRenderer::readFromTargetToSystemMemory()
{
if (!m_pD3DDevice || !m_pTextureOutputSurface || m_renderWidth==0 || m_renderHeight == 0 ||
!m_SystemMemorySurface)
return false;
bool readBuffer = false;
#if defined(_DUMP_SURFACE_READBACK_CONTENTS_)
bool dumpToFile= false;
if (dumpToFile)
{
const char fileName[] = "c:\\temp\\d3dDump.jpg";
HRESULT hres = D3DXSaveSurfaceToFile( fileName, D3DXIFF_JPG,
m_pTextureOutputSurface, NULL , NULL );
if (hres != D3D_OK)
{
}
}
#endif
D3DSURFACE_DESC surfaceDesc;
m_pTextureOutputSurface->GetDesc( &surfaceDesc );
D3DLOCKED_RECT rectInfo;
RECT rectToRead;
rectToRead.top = 0;
rectToRead.left = 0;
rectToRead.bottom = m_renderHeight;
rectToRead.right = m_renderWidth;
DWORD readFlags = D3DLOCK_READONLY;
HRESULT hres = m_pD3DDevice->GetRenderTargetData( m_pTextureOutputSurface,
m_SystemMemorySurface );
if (hres == D3D_OK)
{
hres = m_SystemMemorySurface->LockRect( &rectInfo, &rectToRead, readFlags );
if (hres == D3D_OK)
{
INT pitch = rectInfo.Pitch;
BYTE *data = (BYTE *)rectInfo.pBits;
const unsigned int bytesPerPixel = 4;
unsigned int m_readBackBufferWidth = 0;
unsigned int m_readBackBufferHeight = 0;
m_readBackBuffer.getSize(m_readBackBufferWidth, m_readBackBufferHeight);
BYTE *m_readBackBufferPtr = NULL;
bool replaceReadBackBuffer = false;
if (!m_readBackBufferWidth || !m_readBackBufferHeight ||
m_readBackBufferWidth != m_renderWidth ||
m_readBackBufferHeight != m_renderHeight)
{
m_readBackBuffer.resize(m_renderWidth, m_renderHeight, false);
m_readBackBuffer.getSize(m_readBackBufferWidth, m_readBackBufferHeight);
if (m_readBackBufferWidth != m_renderWidth ||
m_readBackBufferHeight != m_renderHeight)
{
return false;
}
m_readBackBufferPtr = (BYTE *)(m_readBackBuffer.pixels());
}
else
m_readBackBufferPtr = (BYTE *)(m_readBackBuffer.pixels());
if (m_readBackBufferPtr)
{
unsigned int myLineSize = m_renderWidth * bytesPerPixel;
unsigned int offsetMyData = (m_renderHeight-1) * myLineSize;
unsigned int offsetData = 0;
unsigned int i;
for ( i=0 ; i < m_renderHeight; i++ )
{
memcpy( m_readBackBufferPtr + offsetMyData,
data + offsetData,
myLineSize );
offsetMyData -= myLineSize;
offsetData += pitch;
}
readBuffer = true;
}
if (replaceReadBackBuffer)
{
m_readBackBuffer.setPixels( m_readBackBufferPtr, m_renderWidth,
m_renderHeight );
delete[] m_readBackBufferPtr;
}
m_readBackBufferPtr = 0;
hres = m_SystemMemorySurface->UnlockRect();
}
}
return readBuffer;
}
#endif