void GFXDrawUtil::drawRect( const Point2F &upperLeft, const Point2F &lowerRight, const ColorI &color )
{
   //
   // Convert Box   a----------x
   //               |          |
   //               x----------b
   //
   // Into Triangle-Strip Outline
   //               v0-----------v2
   //               | a         x |
   //               |  v1-----v3  |
   //               |   |     |   |
   //               |  v7-----v5  |
   //               | x         b |
   //               v6-----------v4
   //

   // NorthWest and NorthEast facing offset vectors
   // These adjust the thickness of the line, it'd be neat if one day
   // they were passed in as arguments.
   Point2F nw(-0.5f,-0.5f); /*  \  */
   Point2F ne(0.5f,-0.5f); /*  /  */

   GFXVertexBufferHandle<GFXVertexPC> verts (mDevice, 10, GFXBufferTypeVolatile );
   verts.lock();

   F32 ulOffset = 0.5f - mDevice->getFillConventionOffset();

   verts[0].point.set( upperLeft.x + ulOffset + nw.x, upperLeft.y + ulOffset + nw.y, 0.0f );
   verts[1].point.set( upperLeft.x + ulOffset - nw.x, upperLeft.y + ulOffset - nw.y, 0.0f );
   verts[2].point.set( lowerRight.x + ne.x, upperLeft.y + ulOffset + ne.y, 0.0f );
   verts[3].point.set( lowerRight.x - ne.x, upperLeft.y + ulOffset - ne.y, 0.0f );
   verts[4].point.set( lowerRight.x - nw.x, lowerRight.y - nw.y, 0.0f );
   verts[5].point.set( lowerRight.x + nw.x, lowerRight.y + nw.y, 0.0f );
   verts[6].point.set( upperLeft.x + ulOffset - ne.x, lowerRight.y - ne.y, 0.0f );
   verts[7].point.set( upperLeft.x + ulOffset + ne.x, lowerRight.y + ne.y, 0.0f );
   verts[8].point.set( upperLeft.x + ulOffset + nw.x, upperLeft.y + ulOffset + nw.y, 0.0f ); // same as 0
   verts[9].point.set( upperLeft.x + ulOffset - nw.x, upperLeft.y + ulOffset - nw.y, 0.0f ); // same as 1

   for (S32 i=0; i<10; i++)
      verts[i].color = color;

   verts.unlock();
   mDevice->setVertexBuffer( verts );

   mDevice->setStateBlock(mRectFillSB);
   mDevice->setupGenericShaders();
   mDevice->drawPrimitive( GFXTriangleStrip, 0, 8 );
}
Exemple #2
0
//-----------------------------------------------------------------------------
// end
//-----------------------------------------------------------------------------
GFXVertexBuffer * endToBuffer( U32 &numPrims )
{
   mVertBuff.set(GFX, mTempVertBuff.size(), GFXBufferTypeVolatile);
   GFXVertexPCT *verts = mVertBuff.lock();
   dMemcpy( verts, mTempVertBuff.address(), mTempVertBuff.size() * sizeof(GFXVertexPCT) );
   mVertBuff.unlock();

   VERTEX_SIZE_CHECK();

   switch( mType )
   {
      case GFXPointList:
      {
         numPrims = mCurVertIndex;
         break;
      }

      case GFXLineList:
      {
         numPrims = mCurVertIndex / 2;
         break;
      }

      case GFXLineStrip:
      {
         numPrims = mCurVertIndex - 1;
         break;
      }

      case GFXTriangleList:
      {
         numPrims = mCurVertIndex / 3;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         numPrims = mCurVertIndex - 2;
         break;
      }
      case GFXPT_COUNT:
         // handle warning
         break;
   }

   return mVertBuff;
}
Exemple #3
0
void CameraSpline::renderTimeMap()
{
   buildTimeMap();

   gBuilding = true;

   // Build vertex buffer
   GFXVertexBufferHandle<GFXVertexPCT> vb;
   vb.set(GFX, mTimeMap.size(), GFXBufferTypeVolatile);
   void *ptr = vb.lock();
   if(!ptr) return;

   MRandomLCG random(1376312589 * (uintptr_t)this);
   S32 index = 0;
   for(Vector<TimeMap>::iterator itr=mTimeMap.begin(); itr != mTimeMap.end(); itr++)
   {
      Knot a;
      value(itr->mTime, &a, true);

      S32 cr = random.randI(0,255);
      S32 cg = random.randI(0,255);
      S32 cb = random.randI(0,255);
      vb[index].color.set(cr, cg, cb);
      vb[index].point.set(a.mPosition.x, a.mPosition.y, a.mPosition.z);
      index++;
   }

   gBuilding = false;

   vb.unlock();

   // Render the buffer
   GFX->pushWorldMatrix();
   GFX->setupGenericShaders();
   GFX->setVertexBuffer(vb);
   GFX->drawPrimitive(GFXLineStrip,0,index);
   GFX->popWorldMatrix();
}
Exemple #4
0
void ScatterSky::_renderMoon( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
{
   if ( !mMoonMatInst )
      return;

   Point3F moonlightPosition = state->getCameraPosition() - /*mLight->getDirection()*/ mMoonLightDir * state->getFarPlane() * 0.9f;
   F32 dist = (moonlightPosition - state->getCameraPosition()).len();

   // worldRadius = screenRadius * dist / worldToScreen
   // screenRadius = worldRadius / dist * worldToScreen

   //
   F32 screenRadius = GFX->getViewport().extent.y * mMoonScale * 0.5f;
   F32 worldRadius = screenRadius * dist / state->getWorldToScreenScale().y;

   // Calculate Billboard Radius (in world units) to be constant, independent of distance.
   // Takes into account distance, viewport size, and specified size in editor

   F32 BBRadius = worldRadius;


   mMatrixSet->restoreSceneViewProjection();

   if ( state->isReflectPass() )
      mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() );

   mMatrixSet->setWorld( MatrixF::Identity );

   // Initialize points with basic info
   Point3F points[4];
   points[0] = Point3F(-BBRadius, 0.0, -BBRadius);
   points[1] = Point3F( -BBRadius, 0.0, BBRadius);
   points[2] = Point3F( BBRadius, 0.0,  BBRadius);
   points[3] = Point3F( BBRadius, 0.0,  -BBRadius);

   static const Point2F sCoords[4] =
   {
      Point2F( 0.0f, 0.0f ),
      Point2F( 0.0f, 1.0f ),
      Point2F( 1.0f, 1.0f ),
      Point2F( 1.0f, 0.0f )
   };

   // Get info we need to adjust points
   const MatrixF &camView = state->getCameraTransform();

   // Finalize points
   for(int i = 0; i < 4; i++)
   {
      // align with camera
      camView.mulV(points[i]);
      // offset
      points[i] += moonlightPosition;
   }

   // Vertex color.
   ColorF moonVertColor( 1.0f, 1.0f, 1.0f, mNightInterpolant );

   // Copy points to buffer.

   GFXVertexBufferHandle< GFXVertexPCT > vb;
   vb.set( GFX, 4, GFXBufferTypeVolatile );
   GFXVertexPCT *pVert = vb.lock();

   for ( S32 i = 0; i < 4; i++ )
   {
      pVert->color.set( moonVertColor );
      pVert->point.set( points[i] );
      pVert->texCoord.set( sCoords[i].x, sCoords[i].y );
      pVert++;
   }

   vb.unlock();

   // Setup SceneData struct.

   SceneData sgData;
   sgData.wireframe = GFXDevice::getWireframe();
   sgData.visibility = 1.0f;

   // Draw it

   while ( mMoonMatInst->setupPass( state, sgData ) )
   {
      mMoonMatInst->setTransforms( *mMatrixSet, state );
      mMoonMatInst->setSceneInfo( state, sgData );

      GFX->setVertexBuffer( vb );
      GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
   }
}
Exemple #5
0
void TerrainBlock::_updateBaseTexture(bool writeToCache)
{
   if ( !mBaseShader && !_initBaseShader() )
      return;

   // This can sometimes occur outside a begin/end scene.
   const bool sceneBegun = GFX->canCurrentlyRender();
   if ( !sceneBegun )
      GFX->beginScene();

   GFXDEBUGEVENT_SCOPE( TerrainBlock_UpdateBaseTexture, ColorI::GREEN );

   PROFILE_SCOPE( TerrainBlock_UpdateBaseTexture );

   GFXTransformSaver saver;

   const U32 maxTextureSize = GFX->getCardProfiler()->queryProfile( "maxTextureSize", 1024 );

   U32 baseTexSize = getNextPow2( mBaseTexSize );
   baseTexSize = getMin( maxTextureSize, baseTexSize );
   Point2I destSize( baseTexSize, baseTexSize );

   // Setup geometry
   GFXVertexBufferHandle<GFXVertexPT> vb;
   {
      F32 copyOffsetX = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.x;
      F32 copyOffsetY = 2.0f * GFX->getFillConventionOffset() / (F32)destSize.y;

      GFXVertexPT points[4];
      points[0].point = Point3F(1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
      points[0].texCoord = Point2F(1.0, 1.0f);
      points[1].point = Point3F(1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
      points[1].texCoord = Point2F(1.0, 0.0f);
      points[2].point = Point3F(-1.0 - copyOffsetX, -1.0 + copyOffsetY, 0.0);
      points[2].texCoord = Point2F(0.0, 1.0f);
      points[3].point = Point3F(-1.0 - copyOffsetX, 1.0 + copyOffsetY, 0.0);
      points[3].texCoord = Point2F(0.0, 0.0f);

      vb.set( GFX, 4, GFXBufferTypeVolatile );
      GFXVertexPT *ptr = vb.lock();
      if(ptr)
      {
         dMemcpy( ptr, points, sizeof(GFXVertexPT) * 4 );
         vb.unlock();
      }
   }

   GFXTexHandle blendTex;

   // If the base texture is already a valid render target then 
   // use it to render to else we create one.
   if (  mBaseTex.isValid() && 
         mBaseTex->isRenderTarget() &&
         mBaseTex->getFormat() == GFXFormatR8G8B8A8 &&
         mBaseTex->getWidth() == destSize.x &&
         mBaseTex->getHeight() == destSize.y )
      blendTex = mBaseTex;
   else
      blendTex.set( destSize.x, destSize.y, GFXFormatR8G8B8A8, &GFXDefaultRenderTargetProfile, "" );

   GFX->pushActiveRenderTarget();   

   // Set our shader stuff
   GFX->setShader( mBaseShader );
   GFX->setShaderConstBuffer( mBaseShaderConsts );
   GFX->setStateBlock( mBaseShaderSB );
   GFX->setVertexBuffer( vb );

   mBaseTarget->attachTexture( GFXTextureTarget::Color0, blendTex );
   GFX->setActiveRenderTarget( mBaseTarget );

   GFX->clear( GFXClearTarget, ColorI(0,0,0,255), 1.0f, 0 );

   GFX->setTexture( 0, mLayerTex );
   mBaseShaderConsts->setSafe( mBaseLayerSizeConst, (F32)mLayerTex->getWidth() );      

   for ( U32 i=0; i < mBaseTextures.size(); i++ )
   {
      GFXTextureObject *tex = mBaseTextures[i];
      if ( !tex )
         continue;

      GFX->setTexture( 1, tex );

      F32 baseSize = mFile->mMaterials[i]->getDiffuseSize();
      F32 scale = 1.0f;
      if ( !mIsZero( baseSize ) )
         scale = getWorldBlockSize() / baseSize;
      
      // A mistake early in development means that texture
      // coords are not flipped correctly.  To compensate
      // we flip the y scale here.
      mBaseShaderConsts->setSafe( mBaseTexScaleConst, Point2F( scale, -scale ) );
      mBaseShaderConsts->setSafe( mBaseTexIdConst, (F32)i );

      GFX->drawPrimitive( GFXTriangleStrip, 0, 2 );
   }

   mBaseTarget->resolve();
   
   GFX->setShader( NULL );
   //GFX->setStateBlock( NULL ); // WHY NOT?
   GFX->setShaderConstBuffer( NULL );
   GFX->setVertexBuffer( NULL );

   GFX->popActiveRenderTarget();

   // End it if we begun it... Yeehaw!
   if ( !sceneBegun )
      GFX->endScene();

   /// Do we cache this sucker?
   if (mBaseTexFormat == NONE || !writeToCache)
   {
      // We didn't cache the result, so set the base texture
      // to the render target we updated.  This should be good
      // for realtime painting cases.
      mBaseTex = blendTex;
   }
   else if (mBaseTexFormat == DDS)
   {
      String cachePath = _getBaseTexCacheFileName();

      FileStream fs;
      if ( fs.open( _getBaseTexCacheFileName(), Torque::FS::File::Write ) )
      {
         // Read back the render target, dxt compress it, and write it to disk.
         GBitmap blendBmp( destSize.x, destSize.y, false, GFXFormatR8G8B8A8 );
         blendTex.copyToBmp( &blendBmp );

         /*
         // Test code for dumping uncompressed bitmap to disk.
         {
         FileStream fs;
         if ( fs.open( "./basetex.png", Torque::FS::File::Write ) )
         {
         blendBmp.writeBitmap( "png", fs );
         fs.close();
         }         
         }
         */

         blendBmp.extrudeMipLevels();

         DDSFile *blendDDS = DDSFile::createDDSFileFromGBitmap( &blendBmp );
         DDSUtil::squishDDS( blendDDS, GFXFormatDXT1 );

         // Write result to file stream
         blendDDS->write( fs );
         
         delete blendDDS;
      }
      fs.close();
   }
   else
   {
      FileStream stream;
      if (!stream.open(_getBaseTexCacheFileName(), Torque::FS::File::Write))
      {
         mBaseTex = blendTex;
         return;
      }

      GBitmap bitmap(blendTex->getWidth(), blendTex->getHeight(), false, GFXFormatR8G8B8);
      blendTex->copyToBmp(&bitmap);
      bitmap.writeBitmap(formatToExtension(mBaseTexFormat), stream);
   }
}
bool DecalManager::prepRenderImage(SceneState* state, const U32 stateKey,
                                   const U32 /*startZone*/, const bool /*modifyBaseState*/)
{
   PROFILE_SCOPE( DecalManager_RenderDecals );

   if ( !smDecalsOn || !mData ) 
      return false;

   if (isLastState(state, stateKey))
      return false;
   setLastState(state, stateKey);

   if ( !state->isDiffusePass() && !state->isReflectPass() )
      return false;

   PROFILE_START( DecalManager_RenderDecals_SphereTreeCull );

   // Grab this before anything here changes it.
   mCuller = state->getFrustum();

   // Populate vector of decal instances to be rendered with all
   // decals from visible decal spheres.

   mDecalQueue.clear();

   const Vector<DecalSphere*> &grid = mData->getGrid();
   
   for ( U32 i = 0; i < grid.size(); i++ )
   {
      const DecalSphere *decalSphere = grid[i];
      const SphereF &worldSphere = decalSphere->mWorldSphere;
      if ( !mCuller.sphereInFrustum( worldSphere.center, worldSphere.radius ) )
         continue;

      // TODO: If each sphere stored its largest decal instance we
      // could do an LOD step on it here and skip adding any of the
      // decals in the sphere.

      mDecalQueue.merge( decalSphere->mItems );
   }

   PROFILE_END();

   PROFILE_START( DecalManager_RenderDecals_Update );

   const U32 &curSimTime = Sim::getCurrentTime();
   const Point2I &viewportExtent = state->getViewportExtent();
   Point3F cameraOffset; 
   F32   decalSize, 
         pixelRadius;
   U32 delta, diff;
   DecalInstance *dinst;

   // Loop through DecalQueue once for preRendering work.
   // 1. Update DecalInstance fade (over time)
   // 2. Clip geometry if flagged to do so.
   // 3. Calculate lod - if decal is far enough away it will not render.
   for ( U32 i = 0; i < mDecalQueue.size(); i++ )
   {
      dinst = mDecalQueue[i];

      // LOD calculation.
      // See TSShapeInstance::setDetailFromDistance for more
      // information on these calculations.
      decalSize = getMax( dinst->mSize, 0.001f );
      pixelRadius = dinst->calcPixelRadius( state );

      // Need to clamp here.
      if ( pixelRadius < dinst->calcEndPixRadius( viewportExtent ) )
      {
         mDecalQueue.erase_fast( i );
         i--;
         continue;
      }

      // We're gonna try to render this decal... so do any 
      // final adjustments to it before rendering.

      // Update fade and delete expired.
      if ( !( dinst->mFlags & PermanentDecal || dinst->mFlags & CustomDecal ) )
      {         
         delta = ( curSimTime - dinst->mCreateTime );
         if ( delta > dinst->mDataBlock->lifeSpan )         
         {            
            diff = delta - dinst->mDataBlock->lifeSpan;
            dinst->mVisibility = 1.0f - (F32)diff / (F32)dinst->mDataBlock->fadeTime;

            if ( dinst->mVisibility <= 0.0f )
            {
               mDecalQueue.erase_fast( i );
               removeDecal( dinst );               
               i--;
               continue;
            }
         }
      }

      // Build clipped geometry for this decal if needed.
      if ( dinst->mFlags & ClipDecal/* && !( dinst->mFlags & CustomDecal ) */)
      {  
         // Turn off the flag so we don't continually try to clip
         // if it fails.
		  if(!clipDecal( dinst ))
		  {
				dinst->mFlags = dinst->mFlags & ~ClipDecal;
				if ( !(dinst->mFlags & CustomDecal) )
				{
					// Clipping failed to get any geometry...

					// Remove it from the render queue.
					mDecalQueue.erase_fast( i );
					i--;

					// If the decal is one placed at run-time (not the editor)
					// then we should also permanently delete the decal instance.
					if ( !(dinst->mFlags & SaveDecal) )
					{
						removeDecal( dinst );
					}
				}       
				// If this is a decal placed by the editor it will be
				// flagged to attempt clipping again the next time it is
				// modified. For now we just skip rendering it.      
				continue;
		  }  
      }

      // If we get here and the decal still does not have any geometry
      // skip rendering it. It must be an editor placed decal that failed
      // to clip any geometry but has not yet been flagged to try again.
      if ( !dinst->mVerts || dinst->mVertCount == 0 || dinst->mIndxCount == 0 )
      {
         mDecalQueue.erase_fast( i );
         i--;
         continue;
      }

      //
      F32 alpha = pixelRadius / (dinst->mDataBlock->startPixRadius * decalSize) - 1.0f;
      if ( dinst->mFlags & CustomDecal )
      {
         alpha = mClampF( alpha, 0.0f, 1.0f );
         alpha *= dinst->mVisibility;
      }
      else
         alpha = mClampF( alpha * dinst->mVisibility, 0.0f, 1.0f );

      //
      for ( U32 v = 0; v < dinst->mVertCount; v++ )
         dinst->mVerts[v].color.set( 255, 255, 255, alpha * 255.0f );
   }

   PROFILE_END();   

   if ( mDecalQueue.empty() )
      return false;

   // Sort queued decals...
   // 1. Editor decals - in render priority order first, creation time second, and material third.
   // 2. Dynamic decals - in render priority order first and creation time second.
   //
   // With the constraint that decals with different render priority cannot
   // be rendered together in the same draw call.

   PROFILE_START( DecalManager_RenderDecals_Sort );
   dQsort( mDecalQueue.address(), mDecalQueue.size(), sizeof(DecalInstance*), cmpDecalRenderOrder );
   PROFILE_END();

   PROFILE_SCOPE( DecalManager_RenderDecals_RenderBatch );

   mPrimBuffs.clear();
   mVBs.clear();

   RenderPassManager *renderPass = state->getRenderPass();

   // Base render instance for convenience we use for convenience.
   // Data shared by all instances we allocate below can be copied
   // from the base instance at the same time.
   MeshRenderInst baseRenderInst;
   baseRenderInst.clear();   

   MatrixF *tempMat = renderPass->allocUniqueXform( MatrixF( true ) );
   MathUtils::getZBiasProjectionMatrix( gDecalBias, mCuller, tempMat );
   baseRenderInst.projection = tempMat;

   baseRenderInst.objectToWorld = &MatrixF::Identity;
   baseRenderInst.worldToCamera = renderPass->allocSharedXform(RenderPassManager::View);

   baseRenderInst.type = RenderPassManager::RIT_Decal;      

   // Make it the sort distance the max distance so that 
   // it renders after all the other opaque geometry in 
   // the prepass bin.
   baseRenderInst.sortDistSq = F32_MAX;

   // Get the best lights for the current camera position.
   LightManager *lm = state->getLightManager();
   if ( lm )
   {
      lm->setupLights(  NULL, 
                        mCuller.getPosition(),
                        mCuller.getTransform().getForwardVector(),
                        mCuller.getFarDist() );
      lm->getBestLights( baseRenderInst.lights, 4 );
      lm->resetLights();
   }

   Vector<DecalBatch> batches;
   DecalBatch *currentBatch = NULL;

   // Loop through DecalQueue collecting them into render batches.
   for ( U32 i = 0; i < mDecalQueue.size(); i++ )
   {
      DecalInstance *decal = mDecalQueue[i];      
      DecalData *data = decal->mDataBlock;
      Material *mat = data->getMaterial();

      if ( currentBatch == NULL )
      {
         // Start a new batch, beginning with this decal.

         batches.increment();
         currentBatch = &batches.last();
         currentBatch->startDecal = i;
         currentBatch->decalCount = 1;
         currentBatch->iCount = decal->mIndxCount;
         currentBatch->vCount = decal->mVertCount;
         currentBatch->mat = mat;
         currentBatch->matInst = decal->mDataBlock->getMaterialInstance();
         currentBatch->priority = decal->getRenderPriority();         
         currentBatch->dynamic = !(decal->mFlags & SaveDecal);

         continue;
      }

      if ( currentBatch->iCount + decal->mIndxCount >= smMaxIndices || 
           currentBatch->vCount + decal->mVertCount >= smMaxVerts ||
           currentBatch->mat != mat ||
           currentBatch->priority != decal->getRenderPriority() ||
           decal->mCustomTex )
      {
         // End batch.

         currentBatch = NULL;
         i--;
         continue;
      }

      // Add on to current batch.
      currentBatch->decalCount++;
      currentBatch->iCount += decal->mIndxCount;
      currentBatch->vCount += decal->mVertCount;
   }

   // Loop through batches allocating buffers and submitting render instances.
   for ( U32 i = 0; i < batches.size(); i++ )
   {
      DecalBatch &currentBatch = batches[i];

      // Allocate buffers...

      GFXVertexBufferHandle<DecalVertex> vb;
      vb.set( GFX, currentBatch.vCount, GFXBufferTypeDynamic );
      DecalVertex *vpPtr = vb.lock();

      GFXPrimitiveBufferHandle pb;
      pb.set( GFX, currentBatch.iCount, 0, GFXBufferTypeDynamic );
      U16 *pbPtr;
      pb.lock( &pbPtr );

      // Copy data into the buffers from all decals in this batch...

      U32 lastDecal = currentBatch.startDecal + currentBatch.decalCount;

      U32 voffset = 0;
      U32 ioffset = 0;

      // This is an ugly hack for ProjectedShadow!
      GFXTextureObject *customTex = NULL;

      for ( U32 j = currentBatch.startDecal; j < lastDecal; j++ )
      {
         DecalInstance *dinst = mDecalQueue[j];

         for ( U32 k = 0; k < dinst->mIndxCount; k++ )
         {
            *( pbPtr + ioffset + k ) = dinst->mIndices[k] + voffset;            
         }

         ioffset += dinst->mIndxCount;

         dMemcpy( vpPtr + voffset, dinst->mVerts, sizeof( DecalVertex ) * dinst->mVertCount );
         voffset += dinst->mVertCount;

         // Ugly hack for ProjectedShadow!
         if ( (dinst->mFlags & CustomDecal) && dinst->mCustomTex != NULL )
            customTex = *dinst->mCustomTex;
      }

      AssertFatal( ioffset == currentBatch.iCount, "bad" );
      AssertFatal( voffset == currentBatch.vCount, "bad" );
        
      pb.unlock();
      vb.unlock();

      // DecalManager must hold handles to these buffers so they remain valid,
      // we don't actually use them elsewhere.
      mPrimBuffs.push_back( pb );
      mVBs.push_back( vb );

      // Submit render inst...

      MeshRenderInst *ri = renderPass->allocInst<MeshRenderInst>();

      *ri = baseRenderInst;

      ri->primBuff = &mPrimBuffs.last();
      ri->vertBuff = &mVBs.last();

      ri->matInst = currentBatch.matInst;

      ri->prim = renderPass->allocPrim();
      ri->prim->type = GFXTriangleList;
      ri->prim->minIndex = 0;
      ri->prim->startIndex = 0;
      ri->prim->numPrimitives = currentBatch.iCount / 3;
      ri->prim->startVertex = 0;
      ri->prim->numVertices = currentBatch.vCount;

      // Ugly hack for ProjectedShadow!
      if ( customTex )
         ri->miscTex = customTex;

      // The decal bin will contain render instances for both decals and decalRoad's.
      // Dynamic decals render last, then editor decals and roads in priority order.
      // DefaultKey is sorted in descending order.
      ri->defaultKey = currentBatch.dynamic ? 0xFFFFFFFF : (U32)currentBatch.priority;
      ri->defaultKey2 = 1;//(U32)lastDecal->mDataBlock;

      renderPass->addInst( ri );
   }

   return false;
}
void GroundPlane::generateGrid( U32 width, U32 height, F32 squareSize,
                                const Point2F& min, const Point2F& max,
                                GFXVertexBufferHandle< VertexType >& outVertices,
                                GFXPrimitiveBufferHandle& outPrimitives )
{
   // Generate the vertices.

   VertexType* vertices = outVertices.lock();
   for( F32 y = min.y; y <= max.y; y += squareSize )
      for( F32 x = min.x; x <= max.x; x += squareSize )
      {
         vertices->point.x = x;
         vertices->point.y = y;
         vertices->point.z = 0.0;

         vertices->texCoord.x = ( x / squareSize ) * mScaleU;
         vertices->texCoord.y = ( y / squareSize ) * -mScaleV;

         vertices->normal.x = 0.0f;
         vertices->normal.y = 0.0f;
         vertices->normal.z = 1.0f;

         vertices->tangent.x = 1.0f;
         vertices->tangent.y = 0.0f;
         vertices->tangent.z = 0.0f;

         vertices->binormal.x = 0.0f;
         vertices->binormal.y = 1.0f;
         vertices->binormal.z = 0.0f;

         vertices++;
      }
   outVertices.unlock();

   // Generate the indices.

   U16* indices;
   outPrimitives.lock( &indices );
   
   U16 corner1 = 0;
   U16 corner2 = 1;
   U16 corner3 = width + 1;
   U16 corner4 = width + 2;
   
   for( U32 y = 0; y < height; ++ y )
   {
      for( U32 x = 0; x < width; ++ x )
      {
         indices[ 0 ] = corner3;
         indices[ 1 ] = corner2;
         indices[ 2 ] = corner1;

         indices += 3;

         indices[ 0 ] = corner3;
         indices[ 1 ] = corner4;
         indices[ 2 ] = corner2;

         indices += 3;

         corner1 ++;
         corner2 ++;
         corner3 ++;
         corner4 ++;
      }

      corner1 ++;
      corner2 ++;
      corner3 ++;
      corner4 ++;
   }

   outPrimitives.unlock();
}
Exemple #8
0
void Sun::_renderCorona( ObjectRenderInst *ri, SceneRenderState *state, BaseMatInstance *overrideMat )
{   
   // Calculate Billboard Radius (in world units) to be constant, independent of distance.
   // Takes into account distance, viewport size, and specified size in editor
   F32 BBRadius = mCoronaWorldRadius;

   mMatrixSet->restoreSceneViewProjection();   
   
   if ( state->isReflectPass() )
      mMatrixSet->setProjection( state->getSceneManager()->getNonClipProjection() );

   //mMatrixSet->setWorld( MatrixF::Identity );

   // Initialize points with basic info
   Point3F points[4];
   points[0] = Point3F(-BBRadius, 0.0, -BBRadius);
   points[1] = Point3F( -BBRadius, 0.0, BBRadius);
   points[2] = Point3F( BBRadius, 0.0,  BBRadius);
   points[3] = Point3F( BBRadius, 0.0,  -BBRadius);

   static const Point2F sCoords[4] = 
   {
      Point2F( 0.0f, 0.0f ),
      Point2F( 0.0f, 1.0f ),      
      Point2F( 1.0f, 1.0f ),
      Point2F( 1.0f, 0.0f )
   };

   // Get info we need to adjust points
   const MatrixF &camView = state->getCameraTransform();

   // Finalize points
   for(S32 i = 0; i < 4; i++)
   {
      // align with camera
      camView.mulV(points[i]);
      // offset
      points[i] += mLightWorldPos;
   }

   ColorF vertColor;
   if ( mCoronaUseLightColor )
      vertColor = mLightColor;
   else
      vertColor = mCoronaTint;

   GFXVertexBufferHandle< GFXVertexPCT > vb;
   vb.set( GFX, 4, GFXBufferTypeVolatile );
   GFXVertexPCT *pVert = vb.lock();
   if(!pVert) return;

   for ( S32 i = 0; i < 4; i++ )
   {
      pVert->color.set( vertColor );
      pVert->point.set( points[i] );
      pVert->texCoord.set( sCoords[i].x, sCoords[i].y );
      pVert++;
   }

   vb.unlock();

   // Setup SceneData struct.

   SceneData sgData;
   sgData.wireframe = GFXDevice::getWireframe();
   sgData.visibility = 1.0f;

   // Draw it

   while ( mCoronaMatInst->setupPass( state, sgData ) )
   {
      mCoronaMatInst->setTransforms( *mMatrixSet, state );
      mCoronaMatInst->setSceneInfo( state, sgData );

      GFX->setVertexBuffer( vb );      
      GFX->drawPrimitive( GFXTriangleFan, 0, 2 );
   }
}
Exemple #9
0
namespace PrimBuild
{
Vector<GFXVertexPCT> mTempVertBuff;
GFXVertexBufferHandle<GFXVertexPCT> mVertBuff;
GFXPrimitiveType  mType;
U32               mCurVertIndex;
ColorI            mCurColor( 255, 255, 255 );
Point2F           mCurTexCoord;
const ColorI      _colWhite( 255, 255, 255, 255 );

#ifdef TORQUE_DEBUG
U32 mMaxVerts;

#define INIT_VERTEX_SIZE(x) mMaxVerts = x;
#define VERTEX_BOUNDS_CHECK() AssertFatal( mCurVertIndex < mMaxVerts, "PrimBuilder encountered an out of bounds vertex! Break and debug!" );

// This next check shouldn't really be used a lot unless you are tracking down
// a specific bug. -pw
#define VERTEX_SIZE_CHECK() AssertFatal( mCurVertIndex <= mMaxVerts, "PrimBuilder allocated more verts than you used! Break and debug or rendering artifacts could occur." );

#else

#define INIT_VERTEX_SIZE(x)
#define VERTEX_BOUNDS_CHECK()
#define VERTEX_SIZE_CHECK()

#endif

//-----------------------------------------------------------------------------
// begin
//-----------------------------------------------------------------------------
void begin( GFXPrimitiveType type, U32 maxVerts )
{
   AssertFatal( type >= GFXPT_FIRST && type < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );

   mType = type;
   mCurVertIndex = 0;
   INIT_VERTEX_SIZE( maxVerts );
   mTempVertBuff.setSize( maxVerts );
}

void beginToBuffer( GFXPrimitiveType type, U32 maxVerts )
{
   AssertFatal( type >= GFXPT_FIRST && type < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );

   mType = type;
   mCurVertIndex = 0;
   INIT_VERTEX_SIZE( maxVerts );
   mTempVertBuff.setSize( maxVerts );
}

//-----------------------------------------------------------------------------
// end
//-----------------------------------------------------------------------------
GFXVertexBuffer * endToBuffer( U32 &numPrims )
{
   mVertBuff.set(GFX, mTempVertBuff.size(), GFXBufferTypeVolatile);
   GFXVertexPCT *verts = mVertBuff.lock();
   dMemcpy( verts, mTempVertBuff.address(), mTempVertBuff.size() * sizeof(GFXVertexPCT) );
   mVertBuff.unlock();

   VERTEX_SIZE_CHECK();

   switch( mType )
   {
      case GFXPointList:
      {
         numPrims = mCurVertIndex;
         break;
      }

      case GFXLineList:
      {
         numPrims = mCurVertIndex / 2;
         break;
      }

      case GFXLineStrip:
      {
         numPrims = mCurVertIndex - 1;
         break;
      }

      case GFXTriangleList:
      {
         numPrims = mCurVertIndex / 3;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         numPrims = mCurVertIndex - 2;
         break;
      }
      case GFXPT_COUNT:
         // handle warning
         break;
   }

   return mVertBuff;
}

void end( bool useGenericShaders )
{
   if ( mCurVertIndex == 0 ) 
      return; 

   VERTEX_SIZE_CHECK();

   U32 vertStride = 1;
   U32 stripStart = 0;

   AssertFatal( mType >= GFXPT_FIRST && mType < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );
               
   switch( mType )
   {
      default:
      case GFXPointList:
      {
         vertStride = 1;
         break;
      }

      case GFXLineList:
      {
         vertStride = 2;
         break;
      }

      case GFXTriangleList:
      {
         vertStride = 3;
         break;
      }

      case GFXLineStrip:
      {
         stripStart = 1;
         vertStride = 1;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         stripStart = 2;
         vertStride = 1;
         break;
      }
   }

   if ( useGenericShaders )
      GFX->setupGenericShaders( GFXDevice::GSModColorTexture );

   const GFXVertexPCT *srcVerts = mTempVertBuff.address();
   U32 numVerts = mCurVertIndex;
   
   // Make sure we don't have a dirty prim buffer left.
   GFX->setPrimitiveBuffer( NULL );

   if ( stripStart > 0 )
   {
      // TODO: Fix this to allow > MAX_DYNAMIC_VERTS!

      U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
      mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

      GFXVertexPCT *verts = mVertBuff.lock();
      dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
      mVertBuff.unlock();

      U32 numPrims = ( copyVerts / vertStride ) - stripStart;
      GFX->setVertexBuffer( mVertBuff );
      GFX->drawPrimitive( mType, 0, numPrims );
   }
   else
   {
      while ( numVerts > 0 )
      {
         U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
         copyVerts -= copyVerts % vertStride;

         mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

         GFXVertexPCT *verts = mVertBuff.lock();
         dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
         mVertBuff.unlock();

         U32 numPrims = copyVerts / vertStride;
         GFX->setVertexBuffer( mVertBuff );
         GFX->drawPrimitive( mType, 0, numPrims );

         srcVerts += copyVerts;
         numVerts -= copyVerts;
      }
   }
}

//-----------------------------------------------------------------------------
// vertex2f
//-----------------------------------------------------------------------------
void vertex2f( F32 x, F32 y )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.x = x;
   vert->point.y = y;
   vert->point.z = 0.0;
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex3f
//-----------------------------------------------------------------------------
void vertex3f( F32 x, F32 y, F32 z )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.x = x;
   vert->point.y = y;
   vert->point.z = z;
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex3fv
//-----------------------------------------------------------------------------
void vertex3fv( const F32 *data )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.set( data[0], data[1], data[2] );
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}

//-----------------------------------------------------------------------------
// vertex2fv
//-----------------------------------------------------------------------------
void vertex2fv( const F32 *data )
{
   VERTEX_BOUNDS_CHECK();
   GFXVertexPCT *vert = &mTempVertBuff[mCurVertIndex++];

   vert->point.set( data[0], data[1], 0.f );
   vert->color = mCurColor;
   vert->texCoord = mCurTexCoord;
}



//-----------------------------------------------------------------------------
// color
//-----------------------------------------------------------------------------
void color( const ColorI &inColor )
{
   mCurColor = inColor;
}

void color( const ColorF &inColor )
{
   mCurColor = inColor;
}

void color3i( U8 red, U8 green, U8 blue )
{
   mCurColor.set( red, green, blue );
}

void color4i( U8 red, U8 green, U8 blue, U8 alpha )
{
   mCurColor.set( red, green, blue, alpha );
}

void color3f( F32 red, F32 green, F32 blue )
{
   mCurColor.set( U8( red * 255 ), U8( green * 255 ), U8( blue * 255 ) );
}

void color4f( F32 red, F32 green, F32 blue, F32 alpha )
{
   mCurColor.set( U8( red * 255 ), U8( green * 255 ), U8( blue * 255 ), U8( alpha * 255 ) );
}


//-----------------------------------------------------------------------------
// texCoord
//-----------------------------------------------------------------------------
void texCoord2f( F32 x, F32 y )
{
   mCurTexCoord.set( x, y );
}

void shutdown()
{
   mVertBuff = NULL;
}

}  // namespace PrimBuild
Exemple #10
0
void end( bool useGenericShaders )
{
   if ( mCurVertIndex == 0 ) 
      return; 

   VERTEX_SIZE_CHECK();

   U32 vertStride = 1;
   U32 stripStart = 0;

   AssertFatal( mType >= GFXPT_FIRST && mType < GFXPT_COUNT, "PrimBuilder::end() - Bad primitive type!" );
               
   switch( mType )
   {
      default:
      case GFXPointList:
      {
         vertStride = 1;
         break;
      }

      case GFXLineList:
      {
         vertStride = 2;
         break;
      }

      case GFXTriangleList:
      {
         vertStride = 3;
         break;
      }

      case GFXLineStrip:
      {
         stripStart = 1;
         vertStride = 1;
         break;
      }

      case GFXTriangleStrip:
      case GFXTriangleFan:
      {
         stripStart = 2;
         vertStride = 1;
         break;
      }
   }

   if ( useGenericShaders )
      GFX->setupGenericShaders( GFXDevice::GSModColorTexture );

   const GFXVertexPCT *srcVerts = mTempVertBuff.address();
   U32 numVerts = mCurVertIndex;
   
   // Make sure we don't have a dirty prim buffer left.
   GFX->setPrimitiveBuffer( NULL );

   if ( stripStart > 0 )
   {
      // TODO: Fix this to allow > MAX_DYNAMIC_VERTS!

      U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
      mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

      GFXVertexPCT *verts = mVertBuff.lock();
      dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
      mVertBuff.unlock();

      U32 numPrims = ( copyVerts / vertStride ) - stripStart;
      GFX->setVertexBuffer( mVertBuff );
      GFX->drawPrimitive( mType, 0, numPrims );
   }
   else
   {
      while ( numVerts > 0 )
      {
         U32 copyVerts = getMin( (U32)MAX_DYNAMIC_VERTS, numVerts );
         copyVerts -= copyVerts % vertStride;

         mVertBuff.set( GFX, copyVerts, GFXBufferTypeVolatile );

         GFXVertexPCT *verts = mVertBuff.lock();
         dMemcpy( verts, srcVerts, copyVerts * sizeof( GFXVertexPCT ) );
         mVertBuff.unlock();

         U32 numPrims = copyVerts / vertStride;
         GFX->setVertexBuffer( mVertBuff );
         GFX->drawPrimitive( mType, 0, numPrims );

         srcVerts += copyVerts;
         numVerts -= copyVerts;
      }
   }
}