deargui-vpl/ref/virtools/Samples/Behaviors/Shader/Sources/RenderOffscreenView.cpp

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