void CD3DCG::Render(LPDIRECT3DTEXTURE9 &origTex, D3DXVECTOR2 textureSize, D3DXVECTOR2 inputSize, D3DXVECTOR2 viewportSize, D3DXVECTOR2 windowSize) { LPDIRECT3DSURFACE9 pRenderSurface = NULL,pBackBuffer = NULL; frameCnt++; if(!shaderLoaded) return; /* save back buffer render target */ pDevice->GetRenderTarget(0,&pBackBuffer); /* pass 0 represents the original texture */ shaderPasses[0].tex = origTex; shaderPasses[0].outputSize = inputSize; shaderPasses[0].textureSize = textureSize; calculateMatrix(); for(int i=1;i<shaderPasses.size();i++) { switch(shaderPasses[i].scaleParams.scaleTypeX) { case CG_SCALE_ABSOLUTE: shaderPasses[i].outputSize.x = (double)shaderPasses[i].scaleParams.absX; break; case CG_SCALE_SOURCE: shaderPasses[i].outputSize.x = shaderPasses[i-1].outputSize.x * shaderPasses[i].scaleParams.scaleX; break; case CG_SCALE_VIEWPORT: shaderPasses[i].outputSize.x = viewportSize.x * shaderPasses[i].scaleParams.scaleX; break; default: shaderPasses[i].outputSize.x = viewportSize.x; } switch(shaderPasses[i].scaleParams.scaleTypeY) { case CG_SCALE_ABSOLUTE: shaderPasses[i].outputSize.y = (double)shaderPasses[i].scaleParams.absY; break; case CG_SCALE_SOURCE: shaderPasses[i].outputSize.y = shaderPasses[i-1].outputSize.y * shaderPasses[i].scaleParams.scaleY; break; case CG_SCALE_VIEWPORT: shaderPasses[i].outputSize.y = viewportSize.y * shaderPasses[i].scaleParams.scaleY; break; default: shaderPasses[i].outputSize.y = viewportSize.y; } float texSize = npot(max(shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y)); /* make sure the render target exists and has an appropriate size, then set as current render target with last pass as source */ ensureTextureSize(shaderPasses[i].tex,shaderPasses[i].textureSize,D3DXVECTOR2(texSize,texSize),true); shaderPasses[i].tex->GetSurfaceLevel(0,&pRenderSurface); pDevice->SetTexture(0, shaderPasses[i-1].tex); pDevice->SetRenderTarget(0,pRenderSurface); pRenderSurface->Release(); /* set vertex declaration of current pass, update vertex buffer and set base streams */ pDevice->SetVertexDeclaration(shaderPasses[i].vertexDeclaration); setVertexStream(shaderPasses[i].vertexBuffer, shaderPasses[i-1].outputSize,shaderPasses[i-1].textureSize,shaderPasses[i].outputSize); pDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); pDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); pDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, shaderPasses[i].linearFilter?D3DTEXF_LINEAR:D3DTEXF_POINT); pDevice->SetSamplerState(0, D3DSAMP_MINFILTER, shaderPasses[i].linearFilter?D3DTEXF_LINEAR:D3DTEXF_POINT); /* shader vars need to be set after the base vertex streams have been set so they can override them */ setShaderVars(i); cgD3D9BindProgram(shaderPasses[i].cgVertexProgram); checkForCgError("Binding vertex program"); cgD3D9BindProgram(shaderPasses[i].cgFragmentProgram); checkForCgError("Binding fragment program"); /* viewport defines output size */ setViewport(0,0,shaderPasses[i].outputSize.x,shaderPasses[i].outputSize.y); pDevice->BeginScene(); pDevice->DrawPrimitive(D3DPT_TRIANGLESTRIP,0,2); pDevice->EndScene(); } /* take oldes PREV out of deque, make sure it has the same size as the current texture and then set it up as new original texture */ prevPass &oldestPrev = prevPasses.back(); ensureTextureSize(oldestPrev.tex,oldestPrev.textureSize,textureSize,false); if(oldestPrev.vertexBuffer) oldestPrev.vertexBuffer->Release(); origTex = oldestPrev.tex; prevPasses.pop_back(); /* push current original with corresponding vertex buffer to front of PREV deque */ shaderPasses[0].vertexBuffer = shaderPasses[1].vertexBuffer; prevPasses.push_front(prevPass(shaderPasses[0])); /* create new vertex buffer so that next render call will not overwrite the PREV */ pDevice->CreateVertexBuffer(sizeof(VERTEX)*4,D3DUSAGE_WRITEONLY,0,D3DPOOL_MANAGED,&shaderPasses[1].vertexBuffer,NULL); /* set up last pass texture, backbuffer and viewport for final display pass without shaders */ pDevice->SetTexture(0, shaderPasses.back().tex); pDevice->SetRenderTarget(0,pBackBuffer); pBackBuffer->Release(); RECT displayRect=CalculateDisplayRect(shaderPasses.back().outputSize.x,shaderPasses.back().outputSize.y,windowSize.x,windowSize.y); setViewport(displayRect.left,displayRect.top,displayRect.right - displayRect.left,displayRect.bottom - displayRect.top); setVertexStream(shaderPasses.back().vertexBuffer, shaderPasses.back().outputSize,shaderPasses.back().textureSize, D3DXVECTOR2(displayRect.right - displayRect.left,displayRect.bottom - displayRect.top)); pDevice->SetVertexShader(NULL); pDevice->SetPixelShader(NULL); }
void GFXDevice::updateStates(bool forceSetAll /*=false*/) { PROFILE_SCOPE(GFXDevice_updateStates); if(forceSetAll) { bool rememberToEndScene = false; if(!canCurrentlyRender()) { if (!beginScene()) { AssertFatal(false, "GFXDevice::updateStates: Unable to beginScene!"); } rememberToEndScene = true; } setMatrix( GFXMatrixProjection, mProjectionMatrix ); setMatrix( GFXMatrixWorld, mWorldMatrix[mWorldStackSize] ); setMatrix( GFXMatrixView, mViewMatrix ); setVertexDecl( mCurrVertexDecl ); for ( U32 i=0; i < VERTEX_STREAM_COUNT; i++ ) { setVertexStream( i, mCurrentVertexBuffer[i] ); setVertexStreamFrequency( i, mVertexBufferFrequency[i] ); } if( mCurrentPrimitiveBuffer.isValid() ) // This could be NULL when the device is initalizing mCurrentPrimitiveBuffer->prepare(); /// Stateblocks if ( mNewStateBlock ) setStateBlockInternal(mNewStateBlock, true); mCurrentStateBlock = mNewStateBlock; for(U32 i = 0; i < getNumSamplers(); i++) { switch (mTexType[i]) { case GFXTDT_Normal : { mCurrentTexture[i] = mNewTexture[i]; setTextureInternal(i, mCurrentTexture[i]); } break; case GFXTDT_Cube : { mCurrentCubemap[i] = mNewCubemap[i]; if (mCurrentCubemap[i]) mCurrentCubemap[i]->setToTexUnit(i); else setTextureInternal(i, NULL); } break; default: AssertFatal(false, "Unknown texture type!"); break; } } // Set our material setLightMaterialInternal(mCurrentLightMaterial); // Set our lights for(U32 i = 0; i < LIGHT_STAGE_COUNT; i++) { setLightInternal(i, mCurrentLight[i], mCurrentLightEnable[i]); } _updateRenderTargets(); if(rememberToEndScene) endScene(); return; } if (!mStateDirty) return; // Normal update logic begins here. mStateDirty = false; // Update Projection Matrix if( mProjectionMatrixDirty ) { setMatrix( GFXMatrixProjection, mProjectionMatrix ); mProjectionMatrixDirty = false; } // Update World Matrix if( mWorldMatrixDirty ) { setMatrix( GFXMatrixWorld, mWorldMatrix[mWorldStackSize] ); mWorldMatrixDirty = false; } // Update View Matrix if( mViewMatrixDirty ) { setMatrix( GFXMatrixView, mViewMatrix ); mViewMatrixDirty = false; } if( mTextureMatrixCheckDirty ) { for( S32 i = 0; i < getNumSamplers(); i++ ) { if( mTextureMatrixDirty[i] ) { mTextureMatrixDirty[i] = false; setMatrix( (GFXMatrixType)(GFXMatrixTexture + i), mTextureMatrix[i] ); } } mTextureMatrixCheckDirty = false; } // Update the vertex declaration. if ( mVertexDeclDirty ) { setVertexDecl( mCurrVertexDecl ); mVertexDeclDirty = false; } // Update the vertex buffers. for ( U32 i=0; i < VERTEX_STREAM_COUNT; i++ ) { if ( mVertexBufferDirty[i] ) { setVertexStream( i, mCurrentVertexBuffer[i] ); mVertexBufferDirty[i] = false; } if ( mVertexBufferFrequencyDirty[i] ) { setVertexStreamFrequency( i, mVertexBufferFrequency[i] ); mVertexBufferFrequencyDirty[i] = false; } } // Update primitive buffer // // NOTE: It is very important to set the primitive buffer AFTER the vertex buffer // because in order to draw indexed primitives in DX8, the call to SetIndicies // needs to include the base vertex offset, and the DX8 GFXDevice relies on // having mCurrentVB properly assigned before the call to setIndices -patw if( mPrimitiveBufferDirty ) { if( mCurrentPrimitiveBuffer.isValid() ) // This could be NULL when the device is initalizing mCurrentPrimitiveBuffer->prepare(); mPrimitiveBufferDirty = false; } // NOTE: With state blocks, it's now important to update state before setting textures // some devices (e.g. OpenGL) set states on the texture and we need that information before // the texture is activated. if (mStateBlockDirty) { setStateBlockInternal(mNewStateBlock, false); mCurrentStateBlock = mNewStateBlock; mStateBlockDirty = false; } if( mTexturesDirty ) { mTexturesDirty = false; for(U32 i = 0; i < getNumSamplers(); i++) { if(!mTextureDirty[i]) continue; mTextureDirty[i] = false; switch (mTexType[i]) { case GFXTDT_Normal : { mCurrentTexture[i] = mNewTexture[i]; setTextureInternal(i, mCurrentTexture[i]); } break; case GFXTDT_Cube : { mCurrentCubemap[i] = mNewCubemap[i]; if (mCurrentCubemap[i]) mCurrentCubemap[i]->setToTexUnit(i); else setTextureInternal(i, NULL); } break; default: AssertFatal(false, "Unknown texture type!"); break; } } } // Set light material if(mLightMaterialDirty) { setLightMaterialInternal(mCurrentLightMaterial); mLightMaterialDirty = false; } // Set our lights if(mLightsDirty) { mLightsDirty = false; for(U32 i = 0; i < LIGHT_STAGE_COUNT; i++) { if(!mLightDirty[i]) continue; mLightDirty[i] = false; setLightInternal(i, mCurrentLight[i], mCurrentLightEnable[i]); } } _updateRenderTargets(); #ifdef TORQUE_DEBUG_RENDER doParanoidStateCheck(); #endif }
void DeviceGraphicsDX11Geometry::syncToResource (GeometryResource *geometry) { if (geometry->getRecacheData()) { std::size_t num_vertices = geometry->getVertexStream()->size(); std::size_t num_faces; if (geometry->getIndicesStream()) num_faces = geometry->getIndicesStream()->size(); else num_faces = geometry->getVertexStream()->size() / 3; _num_faces = (DTuint) num_faces; _num_vertices = (DTuint) num_vertices; DeviceGraphicsDX11DataStream *vertices_stream = NULL; DeviceGraphicsDX11DataStream *normals_stream = NULL; DeviceGraphicsDX11DataStream *texcoord0_stream = NULL; DeviceGraphicsDX11DataStream *texcoord1_stream = NULL; DeviceGraphicsDX11DataStream *tangents_stream = NULL; DeviceGraphicsDX11DataStream *colors_stream = NULL; DeviceGraphicsDX11DataStream *weights_index_stream = NULL; DeviceGraphicsDX11DataStream *weights_strength_stream = NULL; DeviceGraphicsDX11IndexStream *faces_stream = NULL; Vector3* vertices = NULL; Vector3* normals = NULL; Texcoord2* texcoord0 = NULL; Texcoord2* texcoord1 = NULL; Vector3* tangents = NULL; Color* colors = NULL; WeightsIndex* weights_index = NULL; Texcoord4* weights_strength = NULL; Triangle* faces = NULL; if (geometry->getVertexStream()) { vertices_stream = DeviceGraphicsDX11DataStream::create(); vertices = (Vector3*) vertices_stream->allocateData(sizeof(Vector3) * _num_vertices, DeviceGraphicsDX11DataStream::FMT_3_FLOAT, true); setVertexStream(vertices_stream); _size += sizeof(Vector3) * _num_vertices; } if (geometry->getNormalsStream()) { normals_stream = DeviceGraphicsDX11DataStream::create(); normals = (Vector3*) normals_stream->allocateData(sizeof(Vector3) * _num_vertices, DeviceGraphicsDX11DataStream::FMT_3_FLOAT, false); setNormalStream(normals_stream); _size += sizeof(Vector3) * _num_vertices; } if (geometry->getUVsStream0()) { texcoord0_stream = DeviceGraphicsDX11DataStream::create(); texcoord0 = (Texcoord2*) texcoord0_stream->allocateData(sizeof(Texcoord2) * _num_vertices, DeviceGraphicsDX11DataStream::FMT_2_FLOAT, false); setTexcoordStream(0, texcoord0_stream); _size += sizeof(Texcoord2) * _num_vertices; } if (geometry->getUVsStream1()) { texcoord1_stream = DeviceGraphicsDX11DataStream::create(); texcoord1 = (Texcoord2*) texcoord1_stream->allocateData(sizeof(Texcoord2) * _num_vertices, DeviceGraphicsDX11DataStream::FMT_2_FLOAT, false); setTexcoordStream(1, texcoord1_stream); _size += sizeof(Texcoord2) * _num_vertices; } if (geometry->getTangentsStream()) { tangents_stream = DeviceGraphicsDX11DataStream::create(); tangents = (Vector3*) tangents_stream->allocateData(sizeof(Vector3) * _num_vertices, DeviceGraphicsDX11DataStream::FMT_3_FLOAT, false); setTexcoordStream(2, tangents_stream); _size += sizeof(Vector3) * _num_vertices; } if (geometry->getColorsStream()) { colors_stream = DeviceGraphicsDX11DataStream::create(); colors = (Color*) colors_stream->allocateData(sizeof(Color) * _num_vertices, DeviceGraphicsDX11DataStream::FMT_4_BYTE, false); setColorsStream(colors_stream); _size += sizeof(Color) * _num_vertices; } if (geometry->getWeightsIndexStream()) { weights_index_stream = DeviceGraphicsDX11DataStream::create(); weights_index = (WeightsIndex*) weights_index_stream->allocateData(sizeof(WeightsIndex) * _num_vertices, DeviceGraphicsDX11DataStream::FMT_4_USHORT, false); setWeightsIndexStream(weights_index_stream); _size += sizeof(Texcoord4) * _num_vertices; } if (geometry->getWeightsStrengthStream()) { weights_strength_stream = DeviceGraphicsDX11DataStream::create(); weights_strength = (Texcoord4*) weights_strength_stream->allocateData(sizeof(Texcoord4) * _num_vertices, DeviceGraphicsDX11DataStream::FMT_4_FLOAT, false); setWeightsStrengthStream(weights_strength_stream); _size += sizeof(Texcoord4) * _num_vertices; } if (geometry->getIndicesStream()) { faces_stream = DeviceGraphicsDX11IndexStream::create(); faces = (Triangle*) faces_stream->allocateData(sizeof(Triangle) * _num_faces, false); setIndexStream(faces_stream); _size += sizeof(Triangle) * _num_faces; } // copy data for (DTuint v = 0; v < num_vertices; ++v) { if (vertices) vertices[v] = geometry->getVertexStream()->get(v); if (normals) normals[v] = geometry->getNormalsStream()->get(v); if (texcoord0) texcoord0[v] = geometry->getUVsStream0()->get(v); if (texcoord1) texcoord1[v] = geometry->getUVsStream1()->get(v); if (tangents) tangents[v] = geometry->getTangentsStream()->get(v); if (colors) colors[v] = geometry->getColorsStream()->get(v); if (weights_index) weights_index[v] = geometry->getWeightsIndexStream()->get(v); if (weights_strength) weights_strength[v] = geometry->getWeightsStrengthStream()->get(v); } // copy FaceTri data for (DTuint f = 0; f < num_faces; ++f) { if (faces) faces[f] = geometry->getIndicesStream()->get(f); } if (vertices_stream) vertices_stream->uploadData(); if (normals_stream) normals_stream->uploadData(); if (texcoord0_stream) texcoord0_stream->uploadData(); if (texcoord1_stream) texcoord1_stream->uploadData(); if (tangents_stream) tangents_stream->uploadData(); if (colors_stream) colors_stream->uploadData(); if (weights_index_stream) weights_index_stream->uploadData(); if (weights_strength_stream) weights_strength_stream->uploadData(); if (faces_stream) faces_stream->uploadData(); RELEASE(vertices_stream); RELEASE(normals_stream); RELEASE(texcoord0_stream); RELEASE(texcoord1_stream); RELEASE(tangents_stream); RELEASE(colors_stream); RELEASE(weights_index_stream); RELEASE(weights_strength_stream); RELEASE(faces_stream); geometry->setRecacheData(false); } if (geometry->getRecacheParameters()) { geometry->setRecacheParameters(false); } }