CqImagersource::CqImagersource( const boost::shared_ptr<IqShader>& pShader, bool fActive ) : m_pShader( pShader ), m_pAttributes(), m_pShaderExecEnv(IqShaderExecEnv::create(QGetRenderContextI())) { m_pAttributes = QGetRenderContext()->pattrCurrent(); m_pShader->SetType(Type_Imager); }
CqLightsource::CqLightsource( const boost::shared_ptr<IqShader>& pShader, bool fActive ) : m_pShader( pShader ), m_pAttributes(), m_pTransform(), m_pShaderExecEnv(IqShaderExecEnv::create(QGetRenderContextI())) { // Set a reference with the current attributes. m_pAttributes = QGetRenderContext() ->pattrCurrent(); m_pShader->SetType(Type_Lightsource); m_pTransform = QGetRenderContext() ->ptransCurrent(); }
bool CqCurve::Diceable() { // OK, here the CqCubicCurveSegment line has two options: // 1. split into two more lines // 2. turn into a bilinear patch for rendering // We don't want to go turning into a patch unless absolutely // necessary, since patches cost more. We only want to become a patch // if the current curve is "best handled" as a patch. For now, I'm // choosing to define that the curve is best handled as a patch under // one or more of the following two conditions: // 1. If the maximum width is a significant fraction of the length of // the line (width greater than 0.75 x length; ignoring normals). // 2. If the length of the line (ignoring the width; cos' it's // covered by point 1) is such that it's likely a bilinear // patch would be diced immediately if we created one (so that // patches don't have to get split!). // 3. If the curve crosses the eye plane (m_fDiceable == false). // find the length of the CqLinearCurveSegment line in raster space if( m_splitDecision == Split_Undecided ) { // AGG - 31/07/04 // well, if we follow the above statagy we end up splitting into // far too many grids (with roughly 1 mpg per grid). so after // profiling a few scenes, the fastest method seems to be just // to convert to a patch immediatly. // we really need a native dice for curves but until that time // i reckon this is best. //m_splitDecision = Split_Patch; CqMatrix matCtoR; QGetRenderContext() ->matSpaceToSpace( "camera", "raster", NULL, NULL, QGetRenderContextI()->Time(), matCtoR ); // control hull CqVector2D hull[2] = { vectorCast<CqVector2D>(matCtoR * P()->pValue(0)[0]), vectorCast<CqVector2D>(matCtoR * P()->pValue(1)[0]) }; CqVector2D lengthVector = hull[ 1 ] - hull[ 0 ]; TqFloat lengthraster = lengthVector.Magnitude(); // find the approximate "length" of a diced patch in raster space TqFloat gridlength = GetGridLength(); // decide whether to split into more curve segments or a patch if(( lengthraster < gridlength ) || ( !m_fDiceable )) { // split into a patch m_splitDecision = Split_Patch; } else { // split into smaller curves m_splitDecision = Split_Curve; } } return false; }
/** Initialise the environment for the specified grid size. * \param iGridRes Integer grid resolution. * \param iGridRes Integer grid resolution. */ void CqLightsource::Initialise( TqInt uGridRes, TqInt vGridRes, TqInt microPolygonCount, TqInt shadingPointCount, bool hasValidDerivatives ) { TqInt Uses = gDefLightUses; if ( m_pShader ) { Uses |= m_pShader->Uses(); m_pShaderExecEnv->Initialise( uGridRes, vGridRes, microPolygonCount, shadingPointCount, hasValidDerivatives, m_pAttributes, boost::shared_ptr<IqTransform>(), m_pShader.get(), Uses ); } if ( m_pShader ) m_pShader->Initialise( uGridRes, vGridRes, shadingPointCount, m_pShaderExecEnv.get() ); if ( USES( Uses, EnvVars_L ) ) L() ->Initialise( shadingPointCount ); if ( USES( Uses, EnvVars_Cl ) ) Cl() ->Initialise( shadingPointCount ); // Initialise the geometric parameters in the shader exec env. if ( USES( Uses, EnvVars_P ) ) { CqMatrix mat; QGetRenderContext() ->matSpaceToSpace( "shader", "current", m_pShader->getTransform(), NULL, QGetRenderContextI()->Time(), mat ); P() ->SetPoint( mat * CqVector3D( 0.0f, 0.0f, 0.0f ) ); } if ( USES( Uses, EnvVars_u ) ) u() ->SetFloat( 0.0f ); if ( USES( Uses, EnvVars_v ) ) v() ->SetFloat( 0.0f ); if ( USES( Uses, EnvVars_du ) ) du() ->SetFloat( 0.0f ); if ( USES( Uses, EnvVars_dv ) ) dv() ->SetFloat( 0.0f ); if ( USES( Uses, EnvVars_s ) ) s() ->SetFloat( 0.0f ); if ( USES( Uses, EnvVars_t ) ) t() ->SetFloat( 0.0f ); if ( USES( Uses, EnvVars_N ) ) N() ->SetNormal( CqVector3D( 0.0f, 0.0f, 0.0f ) ); }
void CqImageBuffer::PostSurface( const boost::shared_ptr<CqSurface>& pSurface ) { AQSIS_TIME_SCOPE(Post_surface); // Count the number of total gprims STATS_INC( GPR_created_total ); // Bound the primitive in its current space (camera) space taking into account any motion specification. CqBound Bound; pSurface->Bound(&Bound); // Take into account the displacement bound extension. TqFloat db = 0.0f; CqString strCoordinateSystem( "object" ); const TqFloat* pattrDispclacementBound = pSurface->pAttributes() ->GetFloatAttribute( "displacementbound", "sphere" ); const CqString* pattrCoordinateSystem = pSurface->pAttributes() ->GetStringAttribute( "displacementbound", "coordinatesystem" ); if ( pattrDispclacementBound != 0 ) db = pattrDispclacementBound[ 0 ]; if ( pattrCoordinateSystem != 0 ) strCoordinateSystem = pattrCoordinateSystem[ 0 ]; if ( db != 0.0f ) { CqVector3D vecDB( db, 0, 0 ); const IqTransform* transShaderToWorld = NULL; // Default "shader" space to the displacement shader, unless there isn't one, in which // case use the surface shader. if ( pSurface->pAttributes() ->pshadDisplacement(QGetRenderContextI()->Time()) ) transShaderToWorld = pSurface->pAttributes() ->pshadDisplacement(QGetRenderContextI()->Time()) ->getTransform(); else if ( pSurface->pAttributes() ->pshadSurface(QGetRenderContextI()->Time()) ) transShaderToWorld = pSurface->pAttributes() ->pshadSurface(QGetRenderContextI()->Time()) ->getTransform(); CqMatrix mat; QGetRenderContext() ->matVSpaceToSpace( strCoordinateSystem.c_str(), "camera", transShaderToWorld, pSurface->pTransform().get(), QGetRenderContextI()->Time(), mat ); vecDB = mat * vecDB; db = vecDB.Magnitude(); Bound.vecMax() += db; Bound.vecMin() -= db; } // Check if the surface can be culled. (also adjusts for DOF and converts Bound to raster space). if ( CullSurface( Bound, pSurface ) ) { STATS_INC( GPR_culled ); return ; } // If the primitive has been marked as undiceable by the eyeplane check, then we cannot get a valid // bucket index from it as the projection of the bound would cross the camera plane and therefore give a false // result, so just put it back in the current bucket for further splitting. TqInt XMinb = 0; TqInt YMinb = 0; TqInt XMaxb = 0; TqInt YMaxb = 0; if (! pSurface->IsUndiceable() ) { XMinb = static_cast<TqInt>( Bound.vecMin().x() ) / m_optCache.xBucketSize; YMinb = static_cast<TqInt>( Bound.vecMin().y() ) / m_optCache.yBucketSize; XMaxb = static_cast<TqInt>( Bound.vecMax().x() ) / m_optCache.xBucketSize; YMaxb = static_cast<TqInt>( Bound.vecMax().y() ) / m_optCache.yBucketSize; } XMinb = clamp( XMinb, m_bucketRegion.xMin(), m_bucketRegion.xMax()-1 ); YMinb = clamp( YMinb, m_bucketRegion.yMin(), m_bucketRegion.yMax()-1 ); XMaxb = clamp( XMaxb, m_bucketRegion.xMin(), m_bucketRegion.xMax()-1 ); YMaxb = clamp( YMaxb, m_bucketRegion.yMin(), m_bucketRegion.yMax()-1 ); // Sanity check we are not putting into a bucket that has already been processed. CqBucket* bucket = &Bucket( XMinb, YMinb ); if ( bucket->IsProcessed() ) { // Scan over the buckets that the bound touches, looking for the first one that isn't processed. TqInt yb = YMinb; TqInt xb = XMinb + 1; bool done = false; while(!done && yb <= YMaxb) { while(!done && xb <= XMaxb) { CqBucket& availBucket = Bucket(xb, yb); if(!availBucket.IsProcessed()) { availBucket.AddGPrim(pSurface); done = true; } ++xb; } xb = XMinb; ++yb; } } else { bucket->AddGPrim( pSurface ); } }