MFMatrix *MFRendererState::getDerivedMatrix(MFStateConstant_Matrix matrix) { if(derivedMatrixDirty & MFBIT(matrix)) { switch(matrix) { case MFSCM_View: pMatrixStatesSet[matrix]->Inverse(*pMatrixStates[MFSCM_Camera]); break; case MFSCM_WorldView: pMatrixStatesSet[matrix]->Multiply(*pMatrixStates[MFSCM_World], *getDerivedMatrix(MFSCM_View)); break; case MFSCM_ViewProjection: pMatrixStatesSet[matrix]->Multiply4x4(*getDerivedMatrix(MFSCM_View), *pMatrixStates[MFSCM_Projection]); break; case MFSCM_WorldViewProjection: pMatrixStatesSet[matrix]->Multiply4x4(*pMatrixStates[MFSCM_World], *getDerivedMatrix(MFSCM_ViewProjection)); break; case MFSCM_InverseWorld: pMatrixStatesSet[matrix]->Inverse(*pMatrixStates[MFSCM_World]); break; case MFSCM_InverseViewProjection: pMatrixStatesSet[matrix]->Inverse(*getDerivedMatrix(MFSCM_ViewProjection)); break; default: MFDebug_Assert(false, "Not a derived matrix!"); } derivedMatrixDirty ^= MFBIT(matrix); } return pMatrixStatesSet[matrix]; }
MF_API bool MFTexture_IsAvailable(int format) { MFDisplayDrivers driver = MFTexture_GetCurrentDisplayDriver(); if(driver == MFDD_Unknown) return format == TexFmt_A8R8G8B8; return (gMFTexturePlatformAvailability[format] & MFBIT(driver)) != 0; }
MF_API bool MFTexture_IsFormatAvailable(int format) { MFRendererDrivers driver = MFTexture_GetCurrentDisplayDriver(); if(driver == MFRD_Unknown) return format == ImgFmt_A8R8G8B8; return (gMFImagePlatformAvailability[format] & MFBIT(driver)) != 0; }
static void MFRenderer_CheckRequirements(MFRendererState &state, MFRenderElement &element) { uint32 required[MFSB_CT_TypeCount] = { 0, //MFSB_CT_Bool = 0, 0, //MFSB_CT_Vector, 0, //MFSB_CT_Matrix, MFBIT(MFSCRS_VertexDeclaration) | MFBIT(MFSCRS_BlendState) | MFBIT(MFSCRS_DepthStencilState) | MFBIT(MFSCRS_RasteriserState), 0, //MFSB_CT_Texture, 0, //MFSB_CT_Misc, 0, }; // add required vertex streams MFVertexDeclaration *pDecl = (MFVertexDeclaration*)state.pRenderStates[MFSCRS_VertexDeclaration]; required[MFSB_CT_RenderState] |= pDecl->streamsUsed << MFSCRS_VertexBuffer0; // if we need an index buffer if(element.renderIndexed) required[MFSB_CT_RenderState] |= MFBIT(MFSCRS_IndexBuffer); // add misc requirements if(state.getBool(MFSCB_Animated)) required[MFSB_CT_Misc] |= MFBIT(MFSCMisc_AnimationMatrices) | MFBIT(MFSCMisc_MatrixBatch); if(state.getBool(MFSCB_AlphaTest)) required[MFSB_CT_Vector] |= MFBIT(MFSCV_RenderState); // add material requirements //... // HACK: hardcode the matrices for now... required[MFSB_CT_Matrix] |= MFBIT(MFSCM_World) | MFBIT(MFSCM_Camera) | MFBIT(MFSCM_Projection); // complain about missing states for(int a = 0; a < MFSB_CT_TypeCount; ++a) { uint32 missing = required[a] & ~state.rsSet[a]; if(missing != 0) MissingStates((MFStateBlockConstantType)a, missing); } }
int MFMat_Standard_Begin(MFMaterial *pMaterial, MFRendererState &state) { MFMat_Standard_Data *pData = (MFMat_Standard_Data*)pMaterial->pInstanceData; MFEffectTechnique *pTechnique = NULL; if(pData->pEffect) pTechnique = MFEffect_GetTechnique(pData->pEffect, state); MFDebug_Assert(pTechnique, "No technique!"); MFEffectData_OpenGL &techniqueData = *(MFEffectData_OpenGL*)pTechnique->pPlatformData; if(pTechnique != state.pTechniqueSet) { state.pTechniqueSet = pTechnique; glUseProgram(techniqueData.program); // need to clear all the cache states //... or ignore the state caching for now } // bools /* do a bitscan loop over the bool states uint32 boolState = state.bools & state.rsSet[MFSB_CT_Bool]; uint32 req = pTechnique->renderStateRequirements[MFSB_CT_Bool]; if(req) { uint32 vsReq = pVS->renderStateRequirements[MFSB_CT_Bool]; uint32 psReq = pPS->renderStateRequirements[MFSB_CT_Bool]; if((state.boolsSet & req) != (boolState & req)) { BOOL bools[32]; for(uint32 i=0, b=1; i<MFSCB_Max; ++i, b<<=1) bools[i] = (boolState & b) != 0; if((state.boolsSet & vsReq) != (boolState & vsReq)) pd3dDevice->SetVertexShaderConstantB(0, bools, 32); if((state.boolsSet & psReq) != (boolState & psReq)) pd3dDevice->SetPixelShaderConstantB(0, bools, 32); } } */ // matrices uint32 req = pTechnique->renderStateRequirements[MFSB_CT_Matrix]; uint32 i; while(MFUtil_BitScanReverse(req, &i)) { uint32 b = MFBIT(i); req ^= b; // if(state.pMatrixStatesSet[i] != state.pMatrixStates[i]) { MFMatrix *pM; if(i > MFSCM_DerivedStart) pM = state.getDerivedMatrix((MFStateConstant_Matrix)i); else pM = state.pMatrixStates[i]; // state.pMatrixStatesSet[i] = pM; GLint uniform = techniqueData.uniformLocation[MFSB_CT_Matrix][i]; glUniformMatrix4fv(uniform, 1, GL_TRUE, (float*)pM); } } // vectors req = pTechnique->renderStateRequirements[MFSB_CT_Vector]; while(MFUtil_BitScanReverse(req, &i)) { uint32 b = MFBIT(i); req ^= b; // if(state.pVectorStatesSet[i] != state.pVectorStates[i]) { MFVector *pV = state.pVectorStates[i]; // state.pVectorStatesSet[i] = pV; GLint uniform = techniqueData.uniformLocation[MFSB_CT_Vector][i]; glUniform4fv(uniform, 1, (float*)pV); } } // textures req = pTechnique->renderStateRequirements[MFSB_CT_Texture]; while(MFUtil_BitScanReverse(req, &i)) { req ^= MFBIT(i); MFTexture *pT = state.pTextures[i]; if(state.pTexturesSet[i] != pT) { state.pTexturesSet[i] = pT; glActiveTexture(GL_TEXTURE0 + i); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, (GLuint)(size_t)pT->pInternalData); } /* else { glActiveTexture(GL_TEXTURE0 + i); glDisable(GL_TEXTURE_2D); } */ MFSamplerState *pS = (MFSamplerState*)state.pRenderStates[MFSCRS_DiffuseSamplerState + i]; // if(state.pRenderStatesSet[MFSCRS_DiffuseSamplerState + i] != pS) { // state.pRenderStatesSet[MFSCRS_DiffuseSamplerState + i] = pS; GLint uniform = techniqueData.uniformLocation[MFSB_CT_RenderState][MFSCRS_DiffuseSamplerState + i]; GLint sampler = (GLint)(size_t)pS->pPlatformData; glUniform1i(uniform, i); glBindSampler(i, sampler); } } // blend state MFBlendState *pBlendState = (MFBlendState*)state.pRenderStates[MFSCRS_BlendState]; if(state.pRenderStatesSet[MFSCRS_BlendState] != pBlendState) { state.pRenderStatesSet[MFSCRS_BlendState] = pBlendState; if(pBlendState->stateDesc.bIndependentBlendEnable) { for(int j=0; j<8; ++j) { MFBlendStateDesc::RenderTargetBlendDesc &target = pBlendState->stateDesc.renderTarget[j]; if(target.bEnable) { glEnable(GL_BLEND); glBlendEquationSeparatei(j, glBlendOp[target.blendOp], glBlendOp[target.blendOpAlpha]); glBlendFuncSeparatei(j, glBlendArg[target.srcBlend], glBlendArg[target.destBlend], glBlendArg[target.srcBlendAlpha], glBlendArg[target.destBlendAlpha]); } else glDisable(GL_BLEND); glColorMaski(j, target.writeMask & MFColourWriteEnable_Red, target.writeMask & MFColourWriteEnable_Green, target.writeMask & MFColourWriteEnable_Blue, target.writeMask & MFColourWriteEnable_Alpha); } } else { MFBlendStateDesc::RenderTargetBlendDesc &target = pBlendState->stateDesc.renderTarget[0]; if(target.bEnable) { glEnable(GL_BLEND); glBlendEquationSeparate(glBlendOp[target.blendOp], glBlendOp[target.blendOpAlpha]); glBlendFuncSeparate(glBlendArg[target.srcBlend], glBlendArg[target.destBlend], glBlendArg[target.srcBlendAlpha], glBlendArg[target.destBlendAlpha]); } else glDisable(GL_BLEND); glColorMask(target.writeMask & MFColourWriteEnable_Red, target.writeMask & MFColourWriteEnable_Green, target.writeMask & MFColourWriteEnable_Blue, target.writeMask & MFColourWriteEnable_Alpha); } } // rasteriser state MFRasteriserState *pRasteriserState = (MFRasteriserState*)state.pRenderStates[MFSCRS_RasteriserState]; if(state.pRenderStatesSet[MFSCRS_RasteriserState] != pRasteriserState) { state.pRenderStatesSet[MFSCRS_RasteriserState] = pRasteriserState; switch(pRasteriserState->stateDesc.cullMode) { case MFCullMode_None: glDisable(GL_CULL_FACE); break; case MFCullMode_CCW: glEnable(GL_CULL_FACE); glFrontFace(GL_CW); glCullFace(GL_BACK); break; case MFCullMode_CW: glEnable(GL_CULL_FACE); glFrontFace(GL_CCW); glCullFace(GL_BACK); break; default: MFUNREACHABLE; } } // depth/stencil state MFDepthStencilState *pDSState = (MFDepthStencilState*)state.pRenderStates[MFSCRS_DepthStencilState]; if(state.pRenderStatesSet[MFSCRS_DepthStencilState] != pDSState) { state.pRenderStatesSet[MFSCRS_DepthStencilState] = pDSState; if(pDSState->stateDesc.bDepthEnable) { glEnable(GL_DEPTH_TEST); glDepthFunc(glCompareFunc[pDSState->stateDesc.depthFunc]); glDepthMask(pDSState->stateDesc.depthWriteMask == MFDepthWriteMask_Zero ? GL_FALSE : GL_TRUE); } else glDisable(GL_DEPTH_TEST); } // setup alpha test if(state.boolChanged(MFSCB_AlphaTest) || (state.pVectorStatesSet[MFSCV_RenderState] != state.pVectorStates[MFSCV_RenderState] && state.getBool(MFSCB_AlphaTest))) { MFVector *pRS = state.pVectorStates[MFSCV_RenderState]; state.pVectorStatesSet[MFSCV_RenderState] = pRS; state.boolsSet = (state.boolsSet & ~MFBIT(MFSCB_AlphaTest)) | (state.bools & MFBIT(MFSCB_AlphaTest)); #if !defined(MF_OPENGL_ES) if(state.getBool(MFSCB_AlphaTest)) { glEnable(GL_ALPHA_TEST); glAlphaFunc(GL_GEQUAL, pRS->x); } else glDisable(GL_ALPHA_TEST); #else // TODO: do something here... //I guess we need to implement the alpha test in the shader... #endif } /* // set clour/alpha scales if(state.pVectorStatesSet[MFSCV_User0] != state.pVectorStates[MFSCV_User0]) { MFVector *pMask = state.pVectorStates[MFSCV_User0]; state.pVectorStatesSet[MFSCV_User0] = pMask; // pd3dDevice->SetVertexShaderConstantF(r_colourMask, (float*)pMask, 1); } */ // set animation matrices if(state.getBool(MFSCB_Animated)) { MFDebug_Assert(false, "TODO!"); // for(uint32 b=0; b<state.matrixBatch.numMatrices; b++) // MFRendererPC_SetAnimationMatrix(b, state.animation.pMatrices[state.matrixBatch.pIndices[b]]); } // set viewport if(state.pViewportSet != state.pViewport) { if(!state.pViewport) MFRenderer_ResetViewport(); else MFRenderer_SetViewport(state.pViewport); state.pViewportSet = state.pViewport; } MFCheckForOpenGLError(true); // update the bools 'set' state state.boolsSet = state.bools & state.rsSet[MFSB_CT_Bool]; return 0; }
"PVRTC2_4bpp", "ATCRGB", "ATCRGBA_EXPLICIT", "ATCRGBA", "ASTC", "PSP_DXT1", "PSP_DXT3", "PSP_DXT5", }; uint8 gMFImagePlatformAvailability[4][ImgFmt_Max] = { // normalised { MFBIT(MFRD_D3D9)|MFBIT(MFRD_D3D11)|MFBIT(MFRD_OpenGL)|MFBIT(MFRD_XBox), // ImgFmt_A8R8G8B8 MFBIT(MFRD_D3D9)|MFBIT(MFRD_D3D11)|MFBIT(MFRD_OpenGL)|MFBIT(MFRD_X360)|MFBIT(MFRD_XBox)|MFBIT(MFRD_PSP)|MFBIT(MFRD_PS2), // ImgFmt_A8B8G8R8 MFBIT(MFRD_XBox)|MFBIT(MFRD_OpenGL), // ImgFmt_B8G8R8A8 MFBIT(MFRD_XBox)|MFBIT(MFRD_OpenGL), // ImgFmt_R8G8B8A8 MFBIT(MFRD_D3D9), // ImgFmt_R8G8B8 0, // ImgFmt_B8G8R8 MFBIT(MFRD_D3D11)|MFBIT(MFRD_X360), // ImgFmt_G8R8 MFBIT(MFRD_D3D9)|MFBIT(MFRD_D3D11)|MFBIT(MFRD_X360), // ImgFmt_L8 MFBIT(MFRD_D3D9)|MFBIT(MFRD_D3D11)|MFBIT(MFRD_X360), // ImgFmt_A8 MFBIT(MFRD_D3D9)|MFBIT(MFRD_X360), // ImgFmt_A8L8 MFBIT(MFRD_D3D9)|MFBIT(MFRD_D3D11)|MFBIT(MFRD_OpenGL)|MFBIT(MFRD_X360)|MFBIT(MFRD_XBox), // ImgFmt_R5G6B5 MFBIT(MFRD_X360)|MFBIT(MFRD_XBox), // ImgFmt_R6G5B5
MF_API bool MFTexture_IsAvailableOnPlatform(int format, int platform) { return (gMFTexturePlatformAvailability[format] & MFBIT(platform)) != 0; }
"PSP_A8B8G8R8s", "PSP_B5G6R5s", "PSP_A1B5G5R5s", "PSP_A4B4G4R4s", "PSP_I8s", "PSP_I4s", "PSP_DXT1s", "PSP_DXT3s", "PSP_DXT5s", }; static uint32 gMFTexturePlatformAvailability[TexFmt_Max] = { MFBIT(MFDD_D3D9)|MFBIT(MFDD_D3D11)|MFBIT(MFDD_XBox)|MFBIT(MFDD_OpenGL), // TexFmt_A8R8G8B8 MFBIT(MFDD_PSP)|MFBIT(MFDD_D3D11)|MFBIT(MFDD_XBox)|MFBIT(MFDD_OpenGL)|MFBIT(MFDD_PS2), // TexFmt_A8B8G8R8 MFBIT(MFDD_XBox)|MFBIT(MFDD_OpenGL), // TexFmt_B8G8R8A8 MFBIT(MFDD_XBox)|MFBIT(MFDD_OpenGL), // TexFmt_R8G8B8A8 MFBIT(MFDD_D3D9), // TexFmt_R8G8B8 0, // TexFmt_B8G8R8 MFBIT(MFDD_D3D9)|MFBIT(MFDD_OpenGL), // TexFmt_A2R10G10B10 MFBIT(MFDD_D3D9)|MFBIT(MFDD_D3D11)|MFBIT(MFDD_OpenGL), // TexFmt_A2B10G10R10 MFBIT(MFDD_D3D9)|MFBIT(MFDD_D3D11)|MFBIT(MFDD_OpenGL), // TexFmt_A16B16G16R16 MFBIT(MFDD_D3D9)|MFBIT(MFDD_D3D11)|MFBIT(MFDD_XBox)|MFBIT(MFDD_OpenGL), // TexFmt_R5G6B5 MFBIT(MFDD_XBox), // TexFmt_R6G5B5 MFBIT(MFDD_OpenGL)|MFBIT(MFDD_PSP), // TexFmt_B5G6R5
MF_API MFVertexDeclaration *MFVertex_CreateVertexDeclaration(const MFVertexElement *pElementArray, int elementCount) { // assign the auto format components before calculating the hash MFVertexElement elements[16]; MFCopyMemory(elements, pElementArray, sizeof(MFVertexElement)*elementCount); for(int e=0; e<elementCount; ++e) { if(pElementArray[e].format == MFVDF_Auto) elements[e].format = MFVertex_ChoooseVertexDataTypePlatformSpecific(pElementArray[e].type, pElementArray[e].componentCount); } uint32 hash = MFUtil_HashBuffer(elements, sizeof(MFVertexElement)*elementCount); MFVertexDeclaration *pDecl = (MFVertexDeclaration*)MFResource_Find(hash); if(!pDecl) { pDecl = (MFVertexDeclaration*)MFHeap_AllocAndZero(sizeof(MFVertexDeclaration) + (sizeof(MFVertexElement) + sizeof(MFVertexElementData))*elementCount); pDecl->numElements = elementCount; pDecl->pElements = (MFVertexElement*)&pDecl[1]; pDecl->pElementData = (MFVertexElementData*)&pDecl->pElements[elementCount]; MFCopyMemory(pDecl->pElements, elements, sizeof(MFVertexElement)*elementCount); int streamOffsets[16]; MFZeroMemory(streamOffsets, sizeof(streamOffsets)); // set the element data and calculate the strides for(int e=0; e<elementCount; ++e) { pDecl->pElementData[e].offset = streamOffsets[elements[e].stream]; pDecl->pElementData[e].stride = 0; streamOffsets[elements[e].stream] += gVertexDataStride[elements[e].format]; pDecl->streamsUsed |= MFBIT(elements[e].stream); } // set the strides for each component for(int e=0; e<elementCount; ++e) pDecl->pElementData[e].stride = streamOffsets[elements[e].stream]; if(!MFVertex_CreateVertexDeclarationPlatformSpecific(pDecl)) { MFHeap_Free(pDecl); return NULL; } MFResource_AddResource(pDecl, MFRT_VertexDecl, hash); if(pDecl->streamsUsed != 1) { // create the stream declarations... MFVertexElement streamElements[64]; for(int s=0; s<16; ++s) { if(!(pDecl->streamsUsed & (1 << s))) continue; int numStreamElements = 0; for(int e=0; e<elementCount; ++e) { if(elements[e].stream == s) { streamElements[numStreamElements] = elements[e]; streamElements[numStreamElements].stream = 0; ++numStreamElements; } } if(numStreamElements) pDecl->pStreamDecl[s] = MFVertex_CreateVertexDeclaration(streamElements, numStreamElements); } } } return pDecl; }
int MFMat_Standard_Begin(MFMaterial *pMaterial, MFRendererState &state) { // MFMat_Standard_Data_D3D11 *pData = (MFMat_Standard_Data_D3D11*)pMaterial->pInstanceData; if(state.pMatrixStatesSet[MFSCM_WorldViewProjection] != state.pMatrixStates[MFSCM_WorldViewProjection]) { MFMatrix *pWVP = state.getDerivedMatrix(MFSCM_WorldViewProjection); state.pMatrixStates[MFSCM_WorldViewProjection] = pWVP; // ??? } if(state.pMatrixStatesSet[MFSCM_UV0] != state.pMatrixStates[MFSCM_UV0]) { MFMatrix *pUV0 = state.pMatrixStates[MFSCM_UV0]; state.pMatrixStatesSet[MFSCM_UV0] = pUV0; // ??? } if(state.pVectorStatesSet[MFSCV_MaterialDiffuseColour] != state.pVectorStates[MFSCV_MaterialDiffuseColour]) { MFVector *pDiffuseColour = state.pVectorStates[MFSCV_MaterialDiffuseColour]; state.pVectorStatesSet[MFSCV_MaterialDiffuseColour] = pDiffuseColour; // ??? } bool bDetailPresent = state.isSet(MFSB_CT_Bool, MFSCB_DetailMapSet); bool bDiffusePresent = state.isSet(MFSB_CT_Bool, MFSCB_DiffuseSet); if(bDetailPresent) { // set detail map MFTexture *pDetail = state.pTextures[MFSCT_DetailMap]; if(state.pTexturesSet[MFSCT_DetailMap] != pDetail) { state.pTexturesSet[MFSCT_DetailMap] = pDetail; // ??? // ID3D11ShaderResourceView *pSRV = (ID3D11ShaderResourceView*)pData->textures[pData->diffuseMapIndex].pTexture->pInternalData; // g_pImmediateContext->PSSetShaderResources(0, 1, &pSRV); } // set detail map sampler MFSamplerState *pDetailSamp = (MFSamplerState*)state.pRenderStates[MFSCRS_DetailMapSamplerState]; if(state.pRenderStatesSet[MFSCRS_DetailMapSamplerState] != pDetailSamp) { state.pRenderStatesSet[MFSCRS_DetailMapSamplerState] = pDetailSamp; // ??? // ID3D11ShaderResourceView *pSRV = (ID3D11ShaderResourceView*)pData->textures[pData->diffuseMapIndex].pTexture->pInternalData; // g_pImmediateContext->PSSetShaderResources(0, 1, &pSRV); } } else { if(state.pTexturesSet[MFSCT_DetailMap] != NULL) { state.pTexturesSet[MFSCT_DetailMap] = NULL; // ??? // pd3dDevice->SetTexture(1, NULL); } } if(bDiffusePresent) { // set diffuse map MFTexture *pDiffuse = state.pTextures[MFSCT_Diffuse]; if(state.pTexturesSet[MFSCT_Diffuse] != pDiffuse) { state.pTexturesSet[MFSCT_Diffuse] = pDiffuse; // ??? // ID3D11ShaderResourceView *pSRV = (ID3D11ShaderResourceView*)pData->textures[pData->diffuseMapIndex].pTexture->pInternalData; // g_pImmediateContext->PSSetShaderResources(0, 1, &pSRV); } // set diffuse map sampler MFSamplerState *pDiffuseSamp = (MFSamplerState*)state.pRenderStates[MFSCRS_DiffuseSamplerState]; if(state.pRenderStatesSet[MFSCRS_DiffuseSamplerState] != pDiffuseSamp) { state.pRenderStatesSet[MFSCRS_DiffuseSamplerState] = pDiffuseSamp; // ??? // MFMat_Standard_SetSamplerState(0, pDiffuseSamp); } } else { if(state.pTexturesSet[MFSCT_Diffuse] != NULL) { state.pTexturesSet[MFSCT_Diffuse] = NULL; // ??? // pd3dDevice->SetTexture(0, NULL); } } // configure the texture combiner (can we cache this?) if(state.boolChanged(MFSCB_DetailMapSet) || state.boolChanged(MFSCB_DiffuseSet) || state.boolChanged(MFSCB_User0)) { const uint32 mask = MFBIT(MFSCB_DetailMapSet) | MFBIT(MFSCB_DiffuseSet) | MFBIT(MFSCB_User0); state.boolsSet = (state.boolsSet & ~mask) | (state.bools & mask); g_pImmediateContext->PSSetShader(gpPixelShader, NULL, 0); /* if(bDetailPresent) { pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); pd3dDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); } else { pd3dDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); pd3dDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); if(state.getBool(MFSCB_User0)) { // we need to scale the colour intensity by the vertex alpha since it wont happen during the blend. pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA); pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); // pd3dDevice->SetTextureStageState(1, D3DTSS_CONSTANT, 0); pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); pd3dDevice->SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEMP); pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); } else { pd3dDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); pd3dDevice->SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); } } */ } // blend state MFBlendState *pBlendState = (MFBlendState*)state.pRenderStates[MFSCRS_BlendState]; if(state.pRenderStatesSet[MFSCRS_BlendState] != pBlendState) { state.pRenderStatesSet[MFSCRS_BlendState] = pBlendState; float blend[4] = { 0, 0, 0, 0 }; ID3D11BlendState *pBS = (ID3D11BlendState*)pBlendState->pPlatformData; g_pImmediateContext->OMSetBlendState(pBS, blend, 0xFFFFFFFF); } // rasteriser state MFRasteriserState *pRasteriserState = (MFRasteriserState*)state.pRenderStates[MFSCRS_RasteriserState]; if(state.pRenderStatesSet[MFSCRS_RasteriserState] != pRasteriserState) { state.pRenderStatesSet[MFSCRS_RasteriserState] = pRasteriserState; ID3D11RasterizerState *pRS = (ID3D11RasterizerState*)pRasteriserState->pPlatformData; g_pImmediateContext->RSSetState(pRS); } // depth/stencil state MFDepthStencilState *pDSState = (MFDepthStencilState*)state.pRenderStates[MFSCRS_DepthStencilState]; if(state.pRenderStatesSet[MFSCRS_DepthStencilState] != pDSState) { state.pRenderStatesSet[MFSCRS_DepthStencilState] = pDSState; ID3D11DepthStencilState *pDSS = (ID3D11DepthStencilState*)pDSState->pPlatformData; g_pImmediateContext->OMSetDepthStencilState(pDSS, 0); } // set animation matrices if(state.getBool(MFSCB_Animated)) { MFDebug_Assert(false, "Animation not yet supported! :("); // for(int b=0; b<gNumBonesInBatch; b++) // MFRendererPC_SetAnimationMatrix(b, pAnimMats[pCurrentBatch[b]]); // pd3dDevice->SetVertexShader(pVS_a); } else g_pImmediateContext->VSSetShader(gpVertexShader, NULL, 0); /* g_pImmediateContext->VSSetShader(pVertexShader, NULL, 0); g_pImmediateContext->PSSetShader(pPixelShader, NULL, 0); if(pSetMaterial != pMaterial) { bool premultipliedAlpha = false; static const float blend[4] = {0.0f, 0.0f, 0.0f, 0.0f}; g_pImmediateContext->RSSetState(pData->pRasterizerState); g_pImmediateContext->OMSetBlendState(pData->pBlendState, blend, 0xFFFFFFFF); g_pImmediateContext->VSSetSamplers(0, 1, &pData->pSamplerState); g_pImmediateContext->PSSetSamplers(0, 1, &pData->pSamplerState); g_pImmediateContext->UpdateSubresource(pData->pConstantBuffer, 0, NULL, &pData->cbMaterial, 0, 0); g_pImmediateContext->VSSetConstantBuffers(n_cbMaterial, 1, &pData->pConstantBuffer); g_pImmediateContext->PSSetConstantBuffers(n_cbMaterial, 1, &pData->pConstantBuffer); //// set some render states //if(pData->detailMapIndex) //{ // // HACK: for compound multitexturing // IDirect3DTexture9 *pDiffuse = (IDirect3DTexture9*)pData->pTextures[pData->diffuseMapIndex]->pInternalData; // IDirect3DTexture9 *pDetail = (IDirect3DTexture9*)pData->pTextures[pData->detailMapIndex]->pInternalData; // MFRendererPC_SetTexture(0, pDetail); // MFRendererPC_SetTexture(1, pDiffuse); // MFRendererPC_SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); // MFRendererPC_SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // MFRendererPC_SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_POINT); // MFRendererPC_SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); // MFRendererPC_SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); // MFRendererPC_SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_POINT); // MFRendererPC_SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); // MFRendererPC_SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_CURRENT); // MFRendererPC_SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); // MFRendererPC_SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); // MFRendererPC_SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); // MFRendererPC_SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); // MFRendererPC_SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_TEXTURE); // MFRendererPC_SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_CURRENT); // MFRendererPC_SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); // MFRendererPC_SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_ADD); // MFRendererPC_SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); // MFRendererPC_SetTextureMatrix(pData->textureMatrix); //} //else if(pData->textures[pData->diffuseMapIndex].pTexture) { ID3D11ShaderResourceView *pSRV = (ID3D11ShaderResourceView*)pData->textures[pData->diffuseMapIndex].pTexture->pInternalData; g_pImmediateContext->PSSetShaderResources(0, 1, &pSRV); //MFRendererPC_SetTexture(0, pTexture); //MFRendererPC_SetTexture(1, NULL); //MFRendererPC_SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); //MFRendererPC_SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); //MFRendererPC_SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); //MFRendererPC_SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); //MFRendererPC_SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); //MFRendererPC_SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); //MFRendererPC_SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_CURRENT); //MFRendererPC_SetTextureMatrix(pData->textureMatrix); //premultipliedAlpha = !!(pData->pTextures[pData->diffuseMapIndex]->pTemplateData->flags & TEX_PreMultipliedAlpha); if(premultipliedAlpha) { // // we need to scale the colour intensity by the vertex alpha since it wont happen during the blend. // MFRendererPC_SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_BLENDDIFFUSEALPHA); // MFRendererPC_SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); // //// MFRendererPC_SetTextureStageState(1, D3DTSS_CONSTANT, 0); // // MFRendererPC_SetTextureStageState(1, D3DTSS_COLORARG1, D3DTA_CURRENT); // MFRendererPC_SetTextureStageState(1, D3DTSS_COLORARG2, D3DTA_TEMP); // MFRendererPC_SetTextureStageState(1, D3DTSS_ALPHAARG1, D3DTA_CURRENT); } else { //MFRendererPC_SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); //MFRendererPC_SetTextureStageState(1, D3DTSS_ALPHAOP, D3DTOP_DISABLE); } } else { //MFRendererPC_SetTexture(0, NULL); } //switch (pData->materialType&MF_BlendMask) //{ // case 0: // MFRendererPC_SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE); // break; // case MF_AlphaBlend: // MFRendererPC_SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // MFRendererPC_SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); // MFRendererPC_SetRenderState(D3DRS_SRCBLEND, premultipliedAlpha ? D3DBLEND_ONE : D3DBLEND_SRCALPHA); // MFRendererPC_SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); // break; // case MF_Additive: // MFRendererPC_SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // MFRendererPC_SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); // MFRendererPC_SetRenderState(D3DRS_SRCBLEND, premultipliedAlpha ? D3DBLEND_ONE : D3DBLEND_SRCALPHA); // MFRendererPC_SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); // break; // case MF_Subtractive: // MFRendererPC_SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE); // MFRendererPC_SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_REVSUBTRACT); // MFRendererPC_SetRenderState(D3DRS_SRCBLEND, premultipliedAlpha ? D3DBLEND_ONE : D3DBLEND_SRCALPHA); // MFRendererPC_SetRenderState(D3DRS_DESTBLEND, D3DBLEND_ONE); // break; //} //if (pData->materialType & MF_Mask) //{ // MFRendererPC_SetRenderState(D3DRS_ALPHATESTENABLE, TRUE); // MFRendererPC_SetRenderState(D3DRS_ALPHAFUNC, D3DCMP_GREATEREQUAL); // MFRendererPC_SetRenderState(D3DRS_ALPHAREF, 0xFF); //} //else //{ // MFRendererPC_SetRenderState(D3DRS_ALPHATESTENABLE, FALSE); //} //switch (pData->materialType&MF_CullMode) //{ // case 0<<6: // MFRendererPC_SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); // break; // case 1<<6: // MFRendererPC_SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // break; // case 2<<6: // MFRendererPC_SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); // break; // case 3<<6: // // 'default' ? // MFRendererPC_SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); // break; //} //if(!(pData->materialType&MF_NoZRead) || !(pData->materialType&MF_NoZWrite)) //{ // MFRendererPC_SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE); // MFRendererPC_SetRenderState(D3DRS_ZWRITEENABLE, (pData->materialType&MF_NoZWrite) ? FALSE : TRUE); // MFRendererPC_SetRenderState(D3DRS_ZFUNC, (pData->materialType&MF_NoZRead) ? D3DCMP_ALWAYS : D3DCMP_LESSEQUAL); //} //else //{ // MFRendererPC_SetRenderState(D3DRS_ZENABLE, D3DZB_FALSE); //} } //MFRendererPC_SetColourMask(1, 0, 1, 0); //// set animation matrices... //if (pAnimMats && pCurrentBatch) //{ // for(int b=0; b<gNumBonesInBatch; b++) // MFRendererPC_SetAnimationMatrix(b, pAnimMats[pCurrentBatch[b]]); //} //if(MFRendererPC_GetNumWeights() > 0) // MFRendererPC_SetVertexShader(pVS_a); //else // MFRendererPC_SetVertexShader(pVS_s); */ // update the bools 'set' state state.boolsSet = state.bools & state.rsSet[MFSB_CT_Bool]; return 0; }
static void MFRenderer_RenderElements(MFRendererState &state, MFRenderElement *pElements, int numElements) { // set and mask the Layer + Override states MFRenderer_ApplyRenderStates(state, state.pStateBlocks + MFSBT_Layer, MFSBT_Max - MFSBT_Layer); MFCopyMemory(state.rsMask, state.rsSet, sizeof(state.rsMask)); // for each render element for(int e=0; e<numElements; ++e) { MFRenderElement &element = pElements[e]; // collect state blocks state.pStateBlocks[MFSBT_View] = element.pViewState; state.pStateBlocks[MFSBT_Entity] = element.pEntityState; state.pStateBlocks[MFSBT_Material] = element.pMaterialState; state.pStateBlocks[MFSBT_Geometry] = element.pGeometryState; state.pStateBlocks[MFSBT_MaterialOverride] = element.pMaterialOverrideState; // gather render states MFRenderer_ApplyRenderStates(state, state.pStateBlocks, MFSBT_Layer); // select the technique here? or do it inside RenderElement()? //... // selection criteria: // - animation // - lights // - constants present // - values of constants? #if defined(DEBUG) // check that all required states are set MFRenderer_CheckRequirements(state, element); #endif // apply render state element.pMaterial->pType->materialCallbacks.pBegin(element.pMaterial, state); // set geometry buffers MFVertexDeclaration *pDecl = (MFVertexDeclaration*)state.pRenderStates[MFSCRS_VertexDeclaration]; if(state.pRenderStatesSet[MFSCRS_VertexDeclaration] != pDecl) { state.pRenderStatesSet[MFSCRS_VertexDeclaration] = pDecl; MFVertex_SetVertexDeclaration(pDecl); } for(int vb = 0; vb < 8; ++vb) { if(pDecl->streamsUsed & MFBIT(vb)) { MFVertexBuffer *pVB = (MFVertexBuffer*)state.pRenderStates[MFSCRS_VertexBuffer(vb)]; if(state.pRenderStatesSet[MFSCRS_VertexBuffer(vb)] != pVB) { state.pRenderStatesSet[MFSCRS_VertexBuffer(vb)] = pVB; MFVertex_SetVertexStreamSource(vb, pVB); } } } // render if(element.renderIndexed) { if(state.pRenderStatesSet[MFSCRS_IndexBuffer] != state.pRenderStates[MFSCRS_IndexBuffer]) { MFIndexBuffer *pIB = (MFIndexBuffer*)state.pRenderStates[MFSCRS_IndexBuffer]; state.pRenderStatesSet[MFSCRS_IndexBuffer] = pIB; MFVertex_SetIndexBuffer(pIB); } MFVertexBuffer *pVB = (MFVertexBuffer*)state.pRenderStates[MFSCRS_VertexBuffer0]; int numVertices = pVB->numVerts - (int)element.vertexBufferOffset; MFVertex_RenderIndexedVertices(state.pTechniqueSet, (MFPrimType)element.primType, element.vertexBufferOffset, element.indexBufferOffset, numVertices, element.vertexCount); } else { MFVertex_RenderVertices(state.pTechniqueSet, (MFPrimType)element.primType, element.vertexBufferOffset, element.vertexCount); } } }
static void MFRenderer_ApplyRenderStates(MFRendererState &state, const MFStateBlock **ppStateBlocks, int numStateBlocks) { // prime 'set' flags from mask MFCopyMemory(state.rsSet, state.rsMask, sizeof(state.rsSet)); // for each stateblock in order of precedence for(int sb = numStateBlocks-1; sb >= 0; --sb) { const MFStateBlock *pSB = ppStateBlocks[sb]; if(!pSB) continue; // get a mask of the bools that have not been set uint32 boolsToSet = pSB->boolsSet & ~state.rsSet[MFSB_CT_Bool]; // mark bools as set state.rsSet[MFSB_CT_Bool] |= boolsToSet; // set the bool states state.bools = (state.bools & ~boolsToSet) | (pSB->bools & boolsToSet); // set render states const MFStateBlock::MFStateBlockStateChange *pStateChanges = pSB->GetStateChanges(); for(int s = 0; s < pSB->numStateChanges; ++s) { const MFStateBlock::MFStateBlockStateChange &sc = pStateChanges[s]; // if the state was cleared, of already set, skip it... if(!sc.stateSet || state.isSet(sc.constantType, sc.constant)) continue; // mark as set state.rsSet[sc.constantType] |= MFBIT(sc.constant); // set the state const void *pData = pSB->GetStateData(sc.offset*4); switch(sc.constantType) { case MFSB_CT_Vector: if(state.pVectorStates[sc.constant] != (MFVector*)pData) state.pVectorStates[sc.constant] = (MFVector*)pData; break; case MFSB_CT_Matrix: if(state.pMatrixStates[sc.constant] != (MFMatrix*)pData) { state.pMatrixStates[sc.constant] = (MFMatrix*)pData; // ** HACK ** - Managed matrices need to dirty the derived matrices! if(sc.constant >= MFSCM_ManagedStart && sc.constant < MFSCM_ManagedStart + MFSCM_NumManaged) { switch(sc.constant) { case MFSCM_World: state.derivedMatrixDirty |= MFBIT(MFSCM_WorldView) | MFBIT(MFSCM_WorldViewProjection) | MFBIT(MFSCM_InverseWorld); state.pMatrixStates[MFSCM_WorldView] = NULL; state.pMatrixStates[MFSCM_WorldViewProjection] = NULL; state.pMatrixStates[MFSCM_InverseWorld] = NULL; break; case MFSCM_Camera: state.derivedMatrixDirty |= MFBIT(MFSCM_View) | MFBIT(MFSCM_WorldView) | MFBIT(MFSCM_ViewProjection) | MFBIT(MFSCM_WorldViewProjection) | MFBIT(MFSCM_InverseViewProjection); state.pMatrixStates[MFSCM_View] = NULL; state.pMatrixStates[MFSCM_WorldView] = NULL; state.pMatrixStates[MFSCM_ViewProjection] = NULL; state.pMatrixStates[MFSCM_WorldViewProjection] = NULL; state.pMatrixStates[MFSCM_InverseViewProjection] = NULL; break; case MFSCM_Projection: state.derivedMatrixDirty |= MFBIT(MFSCM_ViewProjection) | MFBIT(MFSCM_WorldViewProjection) | MFBIT(MFSCM_InverseViewProjection); state.pMatrixStates[MFSCM_ViewProjection] = NULL; state.pMatrixStates[MFSCM_WorldViewProjection] = NULL; state.pMatrixStates[MFSCM_InverseViewProjection] = NULL; break; default: MFUNREACHABLE; break; } } } break; case MFSB_CT_Texture: if(state.pTextures[sc.constant] != *(MFTexture**)pData) state.pTextures[sc.constant] = *(MFTexture**)pData; break; case MFSB_CT_RenderState: if(state.pRenderStates[sc.constant] != *(void**)pData) state.pRenderStates[sc.constant] = *(void**)pData; break; case MFSB_CT_Misc: switch(sc.constant) { case MFSCMisc_AnimationMatrices: state.animation = *(MFStateConstant_AnimationMatrices*)pData; break; case MFSCMisc_MatrixBatch: state.matrixBatch = *(MFStateConstant_MatrixBatch*)pData; break; case MFSCMisc_Viewport: state.pViewport = (MFRect*)pData; break; default: MFUNREACHABLE; break; } break; default: continue; } } } }