796 lines
25 KiB
C++
796 lines
25 KiB
C++
#include "stdafx.h"
|
|
#include "RTView.h"
|
|
#include "CKRasterizer.h"
|
|
|
|
//#include "RCKRenderContext.h"
|
|
|
|
#define CombineRTViews_GUID CKGUID(0x43ac0870,0x44fc02ed)
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void ComputeViewRectFromCameraRatio( VxRect& oViewRect, CKCamera& iCam, VxRect& iWindowRect )
|
|
{
|
|
if( !&iCam ) return;
|
|
|
|
int camWidth, camHeight;
|
|
iCam.GetAspectRatio( camWidth, camHeight );
|
|
float camRatio = (float)camHeight / (float)camWidth;
|
|
int pixelHeight = (int)(iWindowRect.GetWidth() * camRatio + 0.5f);
|
|
float homogeneousHeight = pixelHeight / iWindowRect.GetHeight();
|
|
|
|
oViewRect.SetCorners( 0.0f, 0.5f-homogeneousHeight*0.5f, 1.0f, 0.5f+homogeneousHeight*0.5f );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void ConvertToFullSizeIfInvalid( RTView& rtview, CKRenderContext* rc=NULL, BOOL homogen=FALSE )
|
|
{
|
|
if( rtview.rect.GetWidth()<=0 || rtview.rect.GetHeight()<=0 ){
|
|
|
|
rtview.rect.left = 0.0f;
|
|
rtview.rect.top = 0.0f;
|
|
if( rtview.tex ){
|
|
rtview.rect.right = (float)rtview.tex->GetWidth();
|
|
rtview.rect.bottom = (float)rtview.tex->GetHeight();
|
|
} else if ( rc ){
|
|
rtview.rect.right = (float)rc->GetWidth();
|
|
rtview.rect.bottom = (float)rc->GetHeight();
|
|
} else {
|
|
rtview.rect.right = 0.0f;
|
|
rtview.rect.bottom = 0.0f;
|
|
}
|
|
|
|
} else if( homogen ){
|
|
|
|
if( rtview.tex ){
|
|
rtview.rect.left *= rtview.tex->GetWidth();
|
|
rtview.rect.right *= rtview.tex->GetWidth();
|
|
rtview.rect.top *= rtview.tex->GetHeight();
|
|
rtview.rect.bottom *= rtview.tex->GetHeight();
|
|
} else if ( rc ){
|
|
rtview.rect.left *= rc->GetWidth();
|
|
rtview.rect.right *= rc->GetWidth();
|
|
rtview.rect.top *= rc->GetHeight();
|
|
rtview.rect.bottom *= rc->GetHeight();
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifndef NO_CG_SHADERS
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
enum
|
|
{
|
|
PARAM_DEST_VIEW = 0,
|
|
PARAM_RENDEROPTIONS,
|
|
PARAM_BGCOLOR,
|
|
PARAM_SHADER,
|
|
PARAM_SHADER_TECHNIQUE,
|
|
PARAM_VIEW0
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
enum
|
|
{
|
|
LOCAL_COMPID = 0,
|
|
LOCAL_FXPARAMS,
|
|
LOCAL_INPUTVIEWCOUNT,
|
|
LOCAL_HOMOGENEOUSVIEW,
|
|
LOCAL_BUILDPARAMS,
|
|
LOCAL_OUTPUTVIEWCOUNT,
|
|
LOCAL_ADJUSTD3DTEXCOORD
|
|
};
|
|
|
|
#define MAXRT_COUNT 4
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
class innerCombineRTView {
|
|
public:
|
|
innerCombineRTView()
|
|
{
|
|
ropt = 0;
|
|
lastTick = 0xFFFFFFFF;
|
|
}
|
|
XArray<CKParameterLocal*> fxparams;
|
|
CKDWORD ropt;
|
|
CKDWORD lastTick;
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void FillVertex( VxDrawPrimitiveData* dpdata,
|
|
const int viewCount,
|
|
const float x, const float y,
|
|
const float& tx, const float& ty )
|
|
{
|
|
int rectOffset = sizeof(VxRect)/sizeof(float);
|
|
|
|
*dpdata->Positions++ = VxVector4(x, y, 1, 1);
|
|
*dpdata->TexCoord++ = VxUV(tx, ty);
|
|
for( int a=1 ; a<viewCount ; ++a, rectOffset+=sizeof(VxRect)/sizeof(float) ){
|
|
*dpdata->TexCoords[a-1]++ = VxUV( *(&tx + rectOffset),
|
|
*(&ty + rectOffset) );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CKParameterLocal* FindParameterByNameAndType( const XArray<CKParameterLocal*>& params,
|
|
char* paramName,
|
|
CKGUID paramType );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void FillShaderParameters( CKBehavior* beh,
|
|
int firstParamIndex,
|
|
XArray<CKParameterLocal*>& params );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
CKParameterIn* FindBBParamByNameAndType( CKBehavior* beh,
|
|
int firstParamIndex,
|
|
char* paramName,
|
|
CKGUID paramType );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void BuildShaderExposedParams( CKBehavior* beh, int firstParamIndex,
|
|
XArray<CKParameterLocal*>& params );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int GetCurrentOutViewCount( CKBehavior* beh )
|
|
{
|
|
int viewCount=1;
|
|
while( 1 ){
|
|
CKParameterIn* pin = beh->GetInputParameter( PARAM_DEST_VIEW + viewCount );
|
|
if( !pin || pin->GetGUID()!=CKPGUID_TEXTURE )
|
|
break;
|
|
++viewCount;
|
|
}
|
|
return viewCount;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
int GetCurrentViewCount( CKBehavior* beh )
|
|
{
|
|
int viewCount=0;
|
|
int decal = GetCurrentOutViewCount(beh)-1;
|
|
while( 1 ){
|
|
CKParameterIn* pin = beh->GetInputParameter(decal + PARAM_VIEW0 + viewCount );
|
|
if( !pin || pin->GetGUID()!=CKPGUID_RTVIEW ) break;
|
|
++viewCount;
|
|
}
|
|
return viewCount;
|
|
}
|
|
|
|
|
|
/***********************************************/
|
|
// PostProcess Callback
|
|
// Set render options here.
|
|
/***********************************************/
|
|
void CombineRTViewsPostProcess( void *arg )
|
|
{
|
|
CKBehavior* beh = (CKBehavior*)arg;
|
|
CKContext *ctx = beh->GetCKContext();
|
|
CKRenderContext* rc = ctx->GetRenderManager()->GetRenderContext(0);
|
|
if( !rc )
|
|
return;
|
|
|
|
CKRasterizerContext* rstc = rc->GetRasterizerContext();
|
|
if( !rstc ) return;
|
|
|
|
|
|
//--- Get Inner Struct
|
|
innerCombineRTView* icrtv = NULL;
|
|
beh->GetLocalParameterValue( LOCAL_FXPARAMS, &icrtv );
|
|
if( !icrtv ){
|
|
icrtv = new innerCombineRTView();
|
|
beh->SetLocalParameterValue( LOCAL_FXPARAMS, &icrtv );
|
|
}
|
|
|
|
int decal = GetCurrentOutViewCount(beh)-1;
|
|
|
|
//--- Store previous rendering options and apply user's ones.
|
|
///// ... only if tick count is different for this beh (it can be call twice,
|
|
///// and if so, we don't want to overide the first stored rendering options)
|
|
CKTimeManager* timeMan = ctx->GetTimeManager();
|
|
CKDWORD lastTick = timeMan->GetMainTickCount();
|
|
if( icrtv->lastTick != lastTick ){
|
|
//--- definitly store previous rendering options
|
|
icrtv->ropt = rc->GetCurrentRenderOptions();
|
|
icrtv->lastTick = lastTick;
|
|
}
|
|
|
|
CKDWORD ropt = icrtv->ropt;
|
|
beh->GetInputParameterValue(decal+PARAM_RENDEROPTIONS, &ropt );
|
|
|
|
//--- Get Dest RT View.
|
|
CKParameterIn* pin = beh->GetInputParameter( PARAM_DEST_VIEW );
|
|
if( !pin )
|
|
return;
|
|
CKParameter* realPin = pin->GetRealSource();
|
|
if( !realPin )
|
|
return;
|
|
RTView destRTView( realPin );
|
|
|
|
///// If Dest RT View is a texture then force upload to Video Memory
|
|
if( destRTView.tex && !destRTView.tex->IsInVideoMemory() )
|
|
destRTView.tex->EnsureVideoMemory(rc);
|
|
|
|
//--- View Rect is homogeneous ?
|
|
BOOL homogen = FALSE;
|
|
beh->GetLocalParameterValue( LOCAL_HOMOGENEOUSVIEW, &homogen );
|
|
|
|
//--- Check Rect size
|
|
CKCamera* cam = rc->GetAttachedCamera();
|
|
if( cam && (ropt&CK_RENDER_USECAMERARATIO) ){
|
|
homogen = TRUE;
|
|
VxRect windowRect;
|
|
rc->GetWindowRect( windowRect );
|
|
ComputeViewRectFromCameraRatio( destRTView.rect, *cam, windowRect );
|
|
}
|
|
ConvertToFullSizeIfInvalid( destRTView, rc, homogen );
|
|
|
|
//--- Get Background Color
|
|
VxColor bgColor(0, 0, 0, 0);
|
|
beh->GetInputParameterValue(decal+PARAM_BGCOLOR, &bgColor );
|
|
|
|
//--- Get Shader Name
|
|
CKShaderManager* shaderMan = (CKShaderManager*)ctx->GetManagerByGuid( ShaderManagerGUID );
|
|
const char* shaderName = (char*)beh->GetInputParameterReadDataPtr(decal+PARAM_SHADER );
|
|
if( !shaderName )
|
|
|
|
return;
|
|
CKShader* shader = shaderMan->GetShaderByName( shaderName );
|
|
if( !shader ) return;
|
|
|
|
//--- Get Technique Name
|
|
XString techName = (char*)beh->GetInputParameterReadDataPtr(decal+PARAM_SHADER_TECHNIQUE );
|
|
int techIndex = -1;
|
|
if( !shader->GetTechIndexByName( techName, techIndex ) ) return;
|
|
if( !shader->FindNextValidTechnique( techIndex ) ) return;
|
|
|
|
//--- Get Views
|
|
XArray<RTView> view;
|
|
XArray<VxRect> rect;
|
|
CKTexture* lastTexture = NULL;
|
|
|
|
CKRST_RSTFAMILY driverFamily = rc->GetRasterizerContext()->m_Driver->m_2DCaps.Family;
|
|
|
|
float textureOffset = 0.f;
|
|
if (driverFamily == CKRST_DIRECTX)
|
|
{
|
|
// Auto adjust texcoords for D3D if desired
|
|
CKBOOL autoAdjustTexCoord = 1;
|
|
beh->GetLocalParameterValue(LOCAL_ADJUSTD3DTEXCOORD, &autoAdjustTexCoord);
|
|
if (autoAdjustTexCoord)
|
|
{
|
|
textureOffset = 0.5f; // ensure proper sampling of texel center in D3D
|
|
}
|
|
}
|
|
|
|
///// Note: We don't parse RT Views pIns with a for() loop
|
|
///// just to be back-compatible (and thus we don't read viewCount from setting).
|
|
const int viewCount = GetCurrentViewCount( beh );
|
|
int a;
|
|
for( a=0 ; a<viewCount ; ++a ){
|
|
|
|
pin = beh->GetInputParameter( decal + PARAM_VIEW0 + a );
|
|
RTView rtview( pin->GetRealSource() );
|
|
|
|
lastTexture = rtview.tex;
|
|
|
|
//--- Check Rect size
|
|
if( cam && (ropt&CK_RENDER_USECAMERARATIO) ){
|
|
VxRect texRect( 0, 0, 256, 256 );
|
|
if( rtview.tex )
|
|
texRect.SetCorners(0.0f,0.0f,(float)rtview.tex->GetWidth(), (float)rtview.tex->GetHeight() );
|
|
ComputeViewRectFromCameraRatio( rtview.rect, *cam, texRect );
|
|
}
|
|
ConvertToFullSizeIfInvalid( rtview, NULL, homogen );
|
|
|
|
view.PushBack( rtview );
|
|
rect.PushBack( view[a].GetRectangleTexCoords(textureOffset) );
|
|
}
|
|
//--- Set Texture Stages
|
|
for( a=0 ; a<viewCount ; ++a ){
|
|
shaderMan->m_PseudoChannelTexture[a] = view[a].tex;
|
|
}
|
|
//--- Fill Next RTViews with the last One (could be NULL, but
|
|
///// we must use the last one for backcompatibilty reasons).
|
|
for( a=viewCount ; a<MaxChannelCount ; ++a ){
|
|
shaderMan->m_PseudoChannelTexture[a] = lastTexture;
|
|
}
|
|
//--- Get Compilation ID
|
|
int compID = 0;
|
|
beh->GetLocalParameterValue( LOCAL_COMPID, &compID );
|
|
|
|
//--- Get Parameters
|
|
shader->LinkParameters( compID, icrtv->fxparams );
|
|
FillShaderParameters( beh, PARAM_VIEW0+viewCount, icrtv->fxparams );
|
|
|
|
//--- Rendering Initializations
|
|
rc->SetUpdate2DProjEnableFlag(TRUE /*FALSE*/); // Do not update 2D views when SetRenderTarget will be called
|
|
// (We don't render them, this will save some CPU)
|
|
///// Set Destination RTView
|
|
VxRect oldRect;
|
|
rc->GetViewRect( oldRect );
|
|
if( destRTView.tex ){
|
|
#ifdef _XBOX
|
|
destRTView.tex->EnsureVideoMemory(rc);
|
|
#endif
|
|
rc->SetRenderTarget( destRTView.tex );
|
|
}
|
|
|
|
int currentOutRTCount = GetCurrentOutViewCount(beh);
|
|
|
|
if(currentOutRTCount>1){
|
|
int rtIndex = 1;
|
|
for(int i=PARAM_DEST_VIEW+1;i<PARAM_DEST_VIEW+currentOutRTCount;i++){
|
|
|
|
CKTexture *tex = (CKTexture *) beh->GetInputParameterObject(i);
|
|
rc->SetRenderTarget(tex, rtIndex++);
|
|
|
|
}
|
|
}
|
|
|
|
rc->SetViewRect( destRTView.rect );
|
|
|
|
|
|
rstc->m_CurrentFrame |= 0x80000000;
|
|
// Ro: Did not know why this value was set , but it is now
|
|
// used in ckDx9Rasterizer to avoid Device Reset so don't remove...
|
|
rstc->BeginScene();
|
|
rstc->m_CurrentFrame &= ~0x80000000;
|
|
|
|
shaderMan->BeginShaders(rc);
|
|
|
|
///// Clear Destination RTView with background color and no BACKTOFRONT
|
|
VxColor oldbg = rc->GetBackgroundMaterial()->GetDiffuse();
|
|
rc->GetBackgroundMaterial()->SetDiffuse( bgColor );
|
|
rc->Clear( (CK_RENDER_FLAGS)(ropt&(~CK_RENDER_DOBACKTOFRONT)) );
|
|
rc->GetBackgroundMaterial()->SetDiffuse(oldbg);
|
|
|
|
//--- Impede zread and zwrite
|
|
rc->SetState( VXRENDERSTATE_ZWRITEENABLE, FALSE );
|
|
rc->SetState( VXRENDERSTATE_ZENABLE, FALSE );
|
|
|
|
//--- Start Rendering of Final Rectangle
|
|
|
|
///// If we render to the screen the real rendering will occur later
|
|
///// (called by CUIK for example), and we don't want the buffers
|
|
///// to be cleared if we cleared them already (it would override our rendering !).
|
|
if( !destRTView.tex ){
|
|
ropt &= ~CK_RENDER_CLEARZ & ~CK_RENDER_CLEARBACK & ~CK_RENDER_CLEARSTENCIL;
|
|
}
|
|
|
|
///// Set Render Options
|
|
rc->SetCurrentRenderOptions( ropt );
|
|
|
|
///// Set Technique
|
|
shader->SetTechnique( techName );
|
|
|
|
///// Render Final Rectangle with Passes
|
|
#if (DIRECT3D_VERSION<0x0900) && !defined(macintosh)
|
|
const DWORD DPF = (CKRST_DP_STAGES0 << (viewCount-1));
|
|
#else
|
|
const DWORD DPF = CKRST_DP_TRANSFORM | (CKRST_DP_STAGES0 << (viewCount-1));
|
|
#endif
|
|
VxDrawPrimitiveData* dpdata = rc->GetDrawPrimitiveStructure((CKRST_DPFLAGS)DPF, 4);
|
|
VxDrawPrimitiveData dpdataTmp;
|
|
|
|
///// Set PASSCOUNT semantic
|
|
int passCount = shader->Begin(rc);
|
|
shaderMan->m_CurrentPassCount = passCount;
|
|
|
|
//--- Set Automatics Values
|
|
shader->SetParameters( icrtv->fxparams );
|
|
rc->SetValuesOfUsedAutomatics( *shader, NULL, NULL, NULL );
|
|
|
|
for( a=0 ; a<passCount; ++a ){
|
|
|
|
///// Set PASSINDEX semantic
|
|
shaderMan->m_CurrentPassIndex = a;
|
|
shader->ExecutePerPassMeanings( NULL, NULL, NULL, rc );
|
|
|
|
shader->BeginPass(a,rc);
|
|
|
|
memcpy( &dpdataTmp, dpdata, sizeof(VxDrawPrimitiveData) );
|
|
|
|
|
|
VxRect fillRect = rect[0];
|
|
|
|
if (!destRTView.tex || driverFamily != CKRST_OPENGL)
|
|
{
|
|
FillVertex( &dpdataTmp, viewCount,-1, 1, fillRect.left, fillRect.top );
|
|
FillVertex( &dpdataTmp, viewCount, 1, 1, fillRect.right, fillRect.top );
|
|
FillVertex( &dpdataTmp, viewCount,-1,-1, fillRect.left, fillRect.bottom );
|
|
FillVertex( &dpdataTmp, viewCount, 1,-1, fillRect.right, fillRect.bottom );
|
|
}
|
|
else
|
|
{
|
|
// Special case for OpenGL + Render targets
|
|
// When a texture is bound as a render target, the rasterization is inverted on the y axis
|
|
// This require to change the projection matrix (inversion on y axis to compensate), but also invert the winding.
|
|
// This is handled automatically by the OpenGL rasterizer context.
|
|
// Unfortunately, previously written post process shaders ignore the WorldViewProjection matrix
|
|
// and just do a pass through with vertex coordinates. As a result the quad y coords are flipped and winding
|
|
// is inverted -> nothing is drawn. We just compensate by drawing the quad upside down.
|
|
FillVertex( &dpdataTmp, viewCount,-1, -1, fillRect.left, fillRect.top );
|
|
FillVertex( &dpdataTmp, viewCount, 1, -1, fillRect.right, fillRect.top );
|
|
FillVertex( &dpdataTmp, viewCount,-1, 1, fillRect.left, fillRect.bottom );
|
|
FillVertex( &dpdataTmp, viewCount, 1, 1, fillRect.right, fillRect.bottom );
|
|
}
|
|
|
|
|
|
//--- Draw Rectangle
|
|
rc->DrawPrimitive( VX_TRIANGLESTRIP, (WORD*)NULL, 0, dpdata );
|
|
|
|
shader->EndPass(rc);
|
|
}
|
|
|
|
//--- End Rendering of Final Rectangle
|
|
shader->End(rc);
|
|
shaderMan->EndShaders(rc);
|
|
rstc->EndScene();
|
|
|
|
//--- Restore some other stuff
|
|
if( destRTView.tex ){
|
|
rc->SetRenderTarget( NULL );
|
|
}
|
|
|
|
if(currentOutRTCount>1){
|
|
int rtIndex = 0;
|
|
for(int i=1;i<currentOutRTCount;i++){
|
|
rc->SetRenderTarget(NULL,i);
|
|
}
|
|
}
|
|
|
|
rc->SetUpdate2DProjEnableFlag(TRUE); // Allow agin to update 2D views extent
|
|
|
|
|
|
rc->SetViewRect( oldRect );
|
|
|
|
//--- Restore zread and zwrite
|
|
rc->SetState( VXRENDERSTATE_ZWRITEENABLE, TRUE );
|
|
rc->SetState( VXRENDERSTATE_ZENABLE, TRUE );
|
|
|
|
//--- Save the locals
|
|
beh->SetLocalParameterValue( LOCAL_COMPID, &compID );
|
|
}
|
|
|
|
/***********************************************/
|
|
// PreProcess Callback
|
|
// Restore render context options here
|
|
/***********************************************/
|
|
void CombineRTViewsPreProcess( void *arg )
|
|
{
|
|
CKBehavior* beh = (CKBehavior*)arg;
|
|
CKContext *ctx = beh->GetCKContext();
|
|
CKRenderContext* rc = ctx->GetRenderManager()->GetRenderContext(0);
|
|
if( !rc )
|
|
return;
|
|
|
|
//--- Get inner Struct
|
|
innerCombineRTView* icrtv = NULL;
|
|
beh->GetLocalParameterValue( LOCAL_FXPARAMS, &icrtv );
|
|
if( !icrtv )
|
|
return;
|
|
|
|
//--- Restore previous rendering options
|
|
rc->SetCurrentRenderOptions( icrtv->ropt );
|
|
}
|
|
|
|
/***********************************************/
|
|
// Reset render options
|
|
/***********************************************/
|
|
void ResetRenderOptions( CKBehavior* beh )
|
|
{
|
|
CKContext *ctx = beh->GetCKContext();
|
|
CKRenderContext* rc = ctx->GetRenderManager()->GetRenderContext(0);
|
|
if( !rc ) return;
|
|
|
|
//--- Reset rendering options
|
|
CKShaderManager* shaderMan = (CKShaderManager*)ctx->GetManagerByGuid( ShaderManagerGUID );
|
|
if( shaderMan ){
|
|
if( shaderMan->m_RenderOptionsBeforePlay != CK_RENDER_USECURRENTSETTINGS ){
|
|
CKDWORD useCameraRatio = shaderMan->m_RenderOptionsBeforePlay & CK_RENDER_USECAMERARATIO;
|
|
rc->SetCurrentRenderOptions( (CK_RENDER_DEFAULTSETTINGS & ~CK_RENDER_USECAMERARATIO) | useCameraRatio );
|
|
if( !useCameraRatio ){
|
|
VxRect windowRect;
|
|
rc->GetWindowRect( windowRect );
|
|
Vx2DVector zero(0,0);
|
|
Vx2DVector size = windowRect.GetSize();
|
|
VxRect r(zero,size) ;
|
|
rc->SetViewRect( r );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/***********************************************/
|
|
// MAIN
|
|
/***********************************************/
|
|
int CombineRTViews(const CKBehaviorContext& behcontext)
|
|
{
|
|
//--- Standard Behavioral Initialization
|
|
CKBehavior* beh = behcontext.Behavior;
|
|
CKContext *ctx = behcontext.Context;
|
|
|
|
beh->ActivateInput(0, FALSE);
|
|
beh->ActivateOutput(0);
|
|
|
|
CKRenderContext* rc = behcontext.CurrentRenderContext;
|
|
if( !rc ) CKBR_BEHAVIORERROR;
|
|
|
|
//--- Get the Shader Manager
|
|
CKShaderManager* shaderMan = (CKShaderManager*)ctx->GetManagerByGuid( ShaderManagerGUID );
|
|
if( !shaderMan || !shaderMan->IsSupported() ){
|
|
ctx->OutputToConsole("Shader Manager not supported.");
|
|
return CKBR_BEHAVIORERROR;
|
|
}
|
|
//--- Get Dest RT View.
|
|
CKParameterIn* pin = beh->GetInputParameter( PARAM_DEST_VIEW );
|
|
if( !pin ) return CKBR_PARAMETERERROR;
|
|
CKParameter* realPin = pin->GetRealSource();
|
|
if( !realPin ) return CKBR_PARAMETERERROR;
|
|
RTView destRTView( realPin );
|
|
|
|
//--- If we write in a texture then execute both callback now !
|
|
if( destRTView.tex ){
|
|
|
|
CombineRTViewsPostProcess( (void*)beh );
|
|
CombineRTViewsPreProcess( (void*)beh );
|
|
|
|
//--- Otherwise, it's the final post-processing, let render context callthem
|
|
} else {
|
|
//--- Before Transparent Object ?
|
|
CKBOOL beforeTransparent = FALSE;
|
|
|
|
shaderMan->AddTemporaryPostProcessCallBack( CombineRTViewsPostProcess, (void*)beh );
|
|
shaderMan->AddTemporaryPreProcessCallBack( CombineRTViewsPreProcess, (void*)beh );
|
|
}
|
|
|
|
|
|
return CKBR_OK;
|
|
}
|
|
|
|
/***********************************************/
|
|
// CALLBACK
|
|
/***********************************************/
|
|
CKERROR CombineRTViewsCallback(const CKBehaviorContext& behcontext)
|
|
{
|
|
CKBehavior* beh = behcontext.Behavior;
|
|
|
|
switch( behcontext.CallbackMessage ){
|
|
|
|
case CKM_BEHAVIORDELETE:
|
|
case CKM_BEHAVIORDETACH:
|
|
{
|
|
//--- Restore render options
|
|
ResetRenderOptions( beh );
|
|
//CombineRTViewsPreProcess( (void*)beh );
|
|
|
|
//--- Init pfxParams
|
|
innerCombineRTView* icrtv = NULL;
|
|
beh->GetLocalParameterValue( LOCAL_FXPARAMS, &icrtv );
|
|
delete icrtv; icrtv = NULL;
|
|
beh->SetLocalParameterValue( LOCAL_FXPARAMS, &icrtv );
|
|
} break;
|
|
|
|
case CKM_BEHAVIORLOAD:
|
|
case CKM_BEHAVIORATTACH:
|
|
{
|
|
//--- Init compID
|
|
int compID = 0;
|
|
beh->SetLocalParameterValue( LOCAL_COMPID, &compID );
|
|
|
|
//--- Init pfxParams
|
|
innerCombineRTView* icrtv = NULL;
|
|
beh->SetLocalParameterValue( LOCAL_FXPARAMS, &icrtv );
|
|
|
|
if(!beh->GetLocalParameter(LOCAL_OUTPUTVIEWCOUNT)){
|
|
beh->CreateLocalParameter("Output RT View Count",CKPGUID_INT);
|
|
int one = 1;
|
|
beh->SetLocalParameterValue(LOCAL_OUTPUTVIEWCOUNT,&one);
|
|
}
|
|
|
|
if(!beh->GetLocalParameter(LOCAL_ADJUSTD3DTEXCOORD)){
|
|
beh->CreateLocalParameter("Adjust D3D Tex Coord",CKPGUID_BOOL);
|
|
CKBOOL vtrue = 1;
|
|
beh->SetLocalParameterValue(LOCAL_ADJUSTD3DTEXCOORD,&vtrue);
|
|
}
|
|
|
|
} break;
|
|
|
|
case CKM_BEHAVIORRESET:
|
|
{
|
|
//--- Reset render options
|
|
ResetRenderOptions( beh );
|
|
} break;
|
|
|
|
case CKM_BEHAVIORPAUSE:
|
|
{
|
|
if( behcontext.Context->IsInInterfaceMode() ){
|
|
//--- Reset render options
|
|
ResetRenderOptions( beh );
|
|
}
|
|
} break;
|
|
|
|
case CKM_BEHAVIORSETTINGSEDITED:
|
|
{
|
|
//--- Get Wanted Input View Count
|
|
int wantedViewCount = 1;
|
|
beh->GetLocalParameterValue( LOCAL_INPUTVIEWCOUNT, &wantedViewCount );
|
|
|
|
int decal = GetCurrentOutViewCount(beh)-1;
|
|
|
|
//--- Get Previous View Count
|
|
int currentViewCount = GetCurrentViewCount( beh );
|
|
if( currentViewCount != wantedViewCount ){
|
|
|
|
//--- Limit View Count
|
|
if( wantedViewCount<1 ) wantedViewCount = 1;
|
|
if( wantedViewCount>8 ) wantedViewCount = 8;
|
|
beh->SetLocalParameterValue( LOCAL_INPUTVIEWCOUNT, &wantedViewCount );
|
|
|
|
//--- Destroy pIns beyond "View Current"
|
|
int lastPinIndex = beh->GetInputParameterCount();
|
|
while( --lastPinIndex > (decal+PARAM_VIEW0+wantedViewCount-1) ){
|
|
if(beh->GetInputParameter(lastPinIndex)->GetGUID() == CKPGUID_RTVIEW){
|
|
CKDestroyObject( beh->RemoveInputParameter(lastPinIndex) );
|
|
currentViewCount--;
|
|
}
|
|
}
|
|
|
|
//--- Create missing view pIns
|
|
char pInName[8];
|
|
for( int a=currentViewCount ; a<wantedViewCount ; ++a ){
|
|
sprintf( pInName, "View %d", a );
|
|
CKParameterIn* pin = behcontext.Context->CreateCKParameterIn(pInName,CKPGUID_RTVIEW);
|
|
//beh->InsertInputParameter(++lastPinIndex,pin);
|
|
beh->InsertInputParameter(decal+PARAM_VIEW0+a,pin);
|
|
}
|
|
}
|
|
|
|
|
|
//--- Get Wanted Output View Count
|
|
int wantedOutViewCount = 1;
|
|
beh->GetLocalParameterValue( LOCAL_OUTPUTVIEWCOUNT, &wantedOutViewCount );
|
|
|
|
//--- Get Previous View Count
|
|
int currentOutViewCount = GetCurrentOutViewCount( beh );
|
|
|
|
if( currentOutViewCount != wantedOutViewCount){
|
|
|
|
//--- Limit View Count
|
|
if( wantedOutViewCount<1 ) wantedOutViewCount = 1;
|
|
if( wantedOutViewCount>MAXRT_COUNT ) wantedOutViewCount = MAXRT_COUNT;
|
|
|
|
beh->SetLocalParameterValue( LOCAL_OUTPUTVIEWCOUNT, &wantedOutViewCount);
|
|
|
|
//--- Destroy pIns beyond "View Current"
|
|
for(int i=1;i<MAXRT_COUNT;){
|
|
CKParameterIn* pin = beh->GetInputParameter(i);
|
|
if(pin->GetGUID() == CKPGUID_TEXTURE)
|
|
if(i>=wantedOutViewCount){
|
|
CKDestroyObject( beh->RemoveInputParameter(i) );
|
|
--decal;
|
|
} else {
|
|
i++;
|
|
}
|
|
else
|
|
break;
|
|
}
|
|
|
|
//--- Create missing view pIns
|
|
char pInName[16];
|
|
for( int a=currentOutViewCount ; a<wantedOutViewCount ; ++a ){
|
|
sprintf( pInName, "Dest RT %d", a );
|
|
beh->InsertInputParameter(PARAM_DEST_VIEW+a,behcontext.Context->CreateCKParameterIn(pInName, CKPGUID_TEXTURE));
|
|
++decal;
|
|
}
|
|
}
|
|
|
|
//--- Build Exposed Parameters
|
|
BOOL buildExposedParams = FALSE;
|
|
beh->GetLocalParameterValue( LOCAL_BUILDPARAMS, &buildExposedParams );
|
|
|
|
if( buildExposedParams ){
|
|
|
|
//--- Reset buildExposedParams Flag
|
|
buildExposedParams = FALSE;
|
|
beh->SetLocalParameterValue( LOCAL_BUILDPARAMS, &buildExposedParams );
|
|
|
|
//--- Get Shader
|
|
CKContext* ctx = behcontext.Context;
|
|
CKShaderManager* shaderMan = (CKShaderManager*)ctx->GetManagerByGuid( ShaderManagerGUID );
|
|
const char* shaderName = (char*)beh->GetInputParameterReadDataPtr(decal+PARAM_SHADER );
|
|
if( !shaderName ) return CKBR_PARAMETERERROR;
|
|
CKShader* shader = shaderMan->GetShaderByName( shaderName );
|
|
if( !shader ) return CKBR_PARAMETERERROR;
|
|
|
|
//--- Get Compilation ID
|
|
int compID = 0;
|
|
beh->GetLocalParameterValue( LOCAL_COMPID, &compID );
|
|
|
|
//--- Get Inner Struct
|
|
innerCombineRTView* icrtv = NULL;
|
|
beh->GetLocalParameterValue( LOCAL_FXPARAMS, &icrtv );
|
|
if( !icrtv ){
|
|
icrtv = new innerCombineRTView();
|
|
beh->SetLocalParameterValue( LOCAL_FXPARAMS, &icrtv );
|
|
}
|
|
//--- Build Shader Local Parameter Array
|
|
shader->LinkParameters( compID, icrtv->fxparams );
|
|
|
|
//--- Create and Destroy pIns
|
|
int firstParamIndex = decal+PARAM_VIEW0+wantedViewCount;
|
|
BuildShaderExposedParams( beh, firstParamIndex, icrtv->fxparams );
|
|
}
|
|
|
|
} break;
|
|
}
|
|
return CKBR_OK;
|
|
}
|
|
|
|
/***********************************************/
|
|
// PROTO
|
|
/***********************************************/
|
|
CKERROR CreateCombineRTViewsProto(CKBehaviorPrototype **pproto)
|
|
{
|
|
CKBehaviorPrototype *proto = CreateCKBehaviorPrototype("Combine RT Views");
|
|
if(!proto) return CKERR_OUTOFMEMORY;
|
|
|
|
proto->DeclareInput("In");
|
|
proto->DeclareOutput("Out");
|
|
|
|
proto->DeclareInParameter("Dest RT View", CKPGUID_RTVIEW);
|
|
proto->DeclareInParameter("Render Options", CKPGUID_RENDEROPTIONS, "Foreground Sprites,Buffer Swapping,Disable 3D Only,Clear ZBuffer,Buffer Swapping");
|
|
proto->DeclareInParameter("Background Color", CKPGUID_COLOR);
|
|
proto->DeclareInParameter("Shader", CKPGUID_SHADER );
|
|
proto->DeclareInParameter("Technique", CKPGUID_TECHNIQUE );
|
|
proto->DeclareInParameter("View 0", CKPGUID_RTVIEW);
|
|
|
|
proto->DeclareLocalParameter(NULL, CKPGUID_INT); // CompID
|
|
proto->DeclareLocalParameter(NULL, CKPGUID_POINTER);// pFxParams and inner struct
|
|
|
|
proto->DeclareSetting("Input RT View Count", CKPGUID_INT, "1");
|
|
proto->DeclareSetting("Viewports are Homogeneous",CKPGUID_BOOL, "FALSE");
|
|
proto->DeclareSetting("Build Exposed Params",CKPGUID_BOOL, "FALSE");
|
|
proto->DeclareSetting("Output RT View Count", CKPGUID_INT, "1");
|
|
proto->DeclareSetting("Adjust D3D Tex Coord", CKPGUID_BOOL, "TRUE");
|
|
|
|
proto->SetFlags(CK_BEHAVIORPROTOTYPE_NORMAL);
|
|
proto->SetFunction(CombineRTViews);
|
|
proto->SetBehaviorFlags((CK_BEHAVIOR_FLAGS)
|
|
(CKBEHAVIOR_INTERNALLYCREATEDINPUTPARAMS
|
|
| CKBEHAVIOR_VARIABLEPARAMETERINPUTS));
|
|
|
|
proto->SetBehaviorCallbackFct( CombineRTViewsCallback,
|
|
CKCB_BEHAVIORATTACH | CKCB_BEHAVIORLOAD | CKCB_BEHAVIORSETTINGSEDITED |
|
|
CKCB_BEHAVIORDELETE | CKCB_BEHAVIORDETACH |
|
|
CKCB_BEHAVIORPAUSE | CKCB_BEHAVIORRESUME | CKCB_BEHAVIORRESET );
|
|
|
|
*pproto = proto;
|
|
return CK_OK;
|
|
}
|
|
|
|
/***********************************************/
|
|
// DECLARATION
|
|
/***********************************************/
|
|
CKObjectDeclaration *FillBehaviorCombineRTViews()
|
|
{
|
|
CKObjectDeclaration *od = CreateCKObjectDeclaration("Combine RT Views");
|
|
od->SetDescription("Renders a 2D rectangle into a RT View using a Shader to combine up to 8 RT Views.");
|
|
od->SetCategory("Shaders/Rendering");
|
|
od->SetType(CKDLL_BEHAVIORPROTOTYPE);
|
|
od->SetGuid(CombineRTViews_GUID);
|
|
od->SetAuthorGuid(VIRTOOLS_GUID);
|
|
od->SetAuthorName("Virtools");
|
|
od->SetVersion(0x00010000);
|
|
od->SetCreationFunction(CreateCombineRTViewsProto);
|
|
od->SetCompatibleClassId(CKCID_BEOBJECT);
|
|
return od;
|
|
}
|
|
|
|
#endif
|