EffectTranslucency::EffectTranslucency( Texture2D& _RTTarget ) : m_ErrorCode( 0 ), m_RTTarget( _RTTarget ) { ////////////////////////////////////////////////////////////////////////// // Create the materials CHECK_MATERIAL( m_pMatDisplay = CreateMaterial( IDR_SHADER_TRANSLUCENCY_DISPLAY, "./Resources/Shaders/TranslucencyDisplay.hlsl", VertexFormatP3N3G3T2::DESCRIPTOR, "VS", NULL, "PS" ), 1 ); CHECK_MATERIAL( m_pMatBuildZBuffer = CreateMaterial( IDR_SHADER_TRANSLUCENCY_BUILD_ZBUFFER, "./Resources/Shaders/TranslucencyBuildZBuffer.hlsl", VertexFormatP3N3G3T2::DESCRIPTOR, "VS", NULL, "PS" ), 2 ); D3D_SHADER_MACRO pMacros[2] = { { "TARGET_SIZE", "128" }, { NULL, NULL } }; CHECK_MATERIAL( m_pMatDiffusion = CreateMaterial( IDR_SHADER_TRANSLUCENCY_DIFFUSION, "./Resources/Shaders/TranslucencyDiffusion.hlsl", VertexFormatPt4::DESCRIPTOR, "VS", NULL, "PS", pMacros ), 3 ); ////////////////////////////////////////////////////////////////////////// // Build some sphere primitives { Noise N( 1 ); m_pPrimTorusInternal = new Primitive( gs_Device, VertexFormatP3N3G3T2::DESCRIPTOR ); GeometryBuilder::BuildTorus( 80, 50, 1.0f, 0.2f, *m_pPrimTorusInternal, NULL, TweakTorusInternal, &N ); m_pPrimSphereExternal = new Primitive( gs_Device, VertexFormatP3N3G3T2::DESCRIPTOR ); GeometryBuilder::MapperSpherical Mapper( 4.0f, 2.0f ); GeometryBuilder::BuildSphere( 80, 50, *m_pPrimSphereExternal, &Mapper, TweakSphereExternal, &N ); } ////////////////////////////////////////////////////////////////////////// // Build textures & render targets m_pRTZBuffer = new Texture2D( gs_Device, DIFFUSION_SIZE, DIFFUSION_SIZE, 1, PixelFormatRGBA16F::DESCRIPTOR, 1, NULL ); m_pDepthStencil = new Texture2D( gs_Device, DIFFUSION_SIZE, DIFFUSION_SIZE, DepthStencilFormatD32F::DESCRIPTOR ); m_ppRTDiffusion[0] = new Texture2D( gs_Device, DIFFUSION_SIZE, DIFFUSION_SIZE, 1, PixelFormatRGBA16F::DESCRIPTOR, 1, NULL ); m_ppRTDiffusion[1] = new Texture2D( gs_Device, DIFFUSION_SIZE, DIFFUSION_SIZE, 1, PixelFormatRGBA16F::DESCRIPTOR, 1, NULL ); ////////////////////////////////////////////////////////////////////////// // Create the constant buffers m_pCB_Object = new CB<CBObject>( gs_Device, 10 ); m_pCB_Diffusion = new CB<CBDiffusion>( gs_Device, 10 ); m_pCB_Pass = new CB<CBPass>( gs_Device, 11 ); }
EffectParticles::EffectParticles() : m_ErrorCode( 0 ) { ////////////////////////////////////////////////////////////////////////// // Create the materials CHECK_MATERIAL( m_pMatCompute = CreateMaterial( IDR_SHADER_PARTICLES_COMPUTE, "./Resources/Shaders/ParticlesCompute.hlsl", VertexFormatPt4::DESCRIPTOR, "VS", NULL, "PS" ), 1 ); CHECK_MATERIAL( m_pMatDisplay = CreateMaterial( IDR_SHADER_PARTICLES_DISPLAY, "./Resources/Shaders/ParticlesDisplay.hlsl", VertexFormatPt4::DESCRIPTOR, "VS", "GS", "PS" ), 2 ); CHECK_MATERIAL( m_pMatDebugVoronoi = CreateMaterial( IDR_SHADER_PARTICLES_DISPLAY, "./Resources/Shaders/ParticlesDisplay.hlsl", VertexFormatPt4::DESCRIPTOR, "VS_DEBUG", NULL, "PS_DEBUG" ), 3 ); ////////////////////////////////////////////////////////////////////////// // Build the awesome particle primitive // { // VertexFormatP3 Vertices; // m_pPrimParticle = new Primitive( gs_Device, 1, &Vertices, 0, NULL, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, VertexFormatP3::DESCRIPTOR ); // } ////////////////////////////////////////////////////////////////////////// // Build our voronoï texture & our initial positions & data NjFloat2* pCellCenters = new NjFloat2[EFFECT_PARTICLES_COUNT*EFFECT_PARTICLES_COUNT]; { TextureBuilder TB( 1024, 1024 ); VertexFormatPt4* pVertices = new VertexFormatPt4[EFFECT_PARTICLES_COUNT*EFFECT_PARTICLES_COUNT]; BuildVoronoiTexture( TB, pCellCenters, pVertices ); TextureBuilder::ConversionParams Conv = { 0, // int PosR; 1, // int PosG; -1, // int PosB; -1, // int PosA; false, // Position of the height & roughness fields -1, // int PosHeight; -1, // int PosRoughness; // Position of the Material ID -1, // int PosMatID; // Position of the normal fields // 1.0f, // float NormalFactor; // Factor to apply to the height to generate the normals true, -1, // int PosNormalX; -1, // int PosNormalY; -1, // int PosNormalZ; // Position of the AO field // 1.0f, // float AOFactor; // Factor to apply to the height to generate the AO -1, // int PosAO; }; m_pTexVoronoi = TB.CreateTexture( PixelFormatRG32F::DESCRIPTOR, Conv ); m_pPrimParticle = new Primitive( gs_Device, EFFECT_PARTICLES_COUNT*EFFECT_PARTICLES_COUNT, pVertices, 0, NULL, D3D11_PRIMITIVE_TOPOLOGY_POINTLIST, VertexFormatPt4::DESCRIPTOR ); // Build cell centers for ( int ParticleIndex=0; ParticleIndex < EFFECT_PARTICLES_COUNT*EFFECT_PARTICLES_COUNT; ParticleIndex++ ) pCellCenters[ParticleIndex].Set( 0.5f * (pVertices[ParticleIndex].Pt.x + pVertices[ParticleIndex].Pt.z), 0.5f * (pVertices[ParticleIndex].Pt.y + pVertices[ParticleIndex].Pt.w) ); delete[] pVertices; } ////////////////////////////////////////////////////////////////////////// // Build the initial positions & orientations of the particles from the surface of a torus PixelFormatRGBA32F* pInitialPositions = new PixelFormatRGBA32F[EFFECT_PARTICLES_COUNT*EFFECT_PARTICLES_COUNT]; PixelFormatRGBA32F* pInitialNormals = new PixelFormatRGBA32F[EFFECT_PARTICLES_COUNT*EFFECT_PARTICLES_COUNT]; PixelFormatRGBA32F* pInitialTangents = new PixelFormatRGBA32F[EFFECT_PARTICLES_COUNT*EFFECT_PARTICLES_COUNT]; PixelFormatRGBA32F* pScanlinePosition = pInitialPositions; PixelFormatRGBA32F* pScanlineNormal = pInitialNormals; PixelFormatRGBA32F* pScanlineTangent = pInitialTangents; int TotalCount = EFFECT_PARTICLES_COUNT*EFFECT_PARTICLES_COUNT; int ParticlesPerDimension = U32(floorf(powf( float(TotalCount), 1.0f/3.0f ))); float R = 0.5f; // Great radius of the torus float r = 0.2f; // Small radius of the torus for ( int Y=0; Y < EFFECT_PARTICLES_COUNT; Y++ ) for ( int X=0; X < EFFECT_PARTICLES_COUNT; X++, pScanlinePosition++, pScanlineNormal++, pScanlineTangent++ ) { NjFloat2& CellCenter = pCellCenters[EFFECT_PARTICLES_COUNT*Y+X]; float Alpha = TWOPI * X / EFFECT_PARTICLES_COUNT; // Angle on the great circle float Beta = TWOPI * Y / EFFECT_PARTICLES_COUNT; // Angle on the small circle NjFloat3 T( cosf(Alpha), 0.0f, -sinf(Alpha) ); // Gives the direction to the center on the great circle in the Z^X plane NjFloat3 Center = NjFloat3( 0, 0.8f, 0 ) + R * T; // Center on the great circle NjFloat3 Ortho( T.z, 0, -T.x ); // Tangent to the great circle in the Z^X plane NjFloat3 B( 0, 1, 0 ); // Bitangent is obviously, always the Y vector NjFloat3 Normal = cosf(Beta) * T + sinf(Beta) * B; // The normal to the small circle, also the direction to the point on the surface NjFloat3 Tangent = Ortho; NjFloat3 Pos = Center + r * Normal; // Position on the surface of the small circle float Radius = R + r * cosf(Beta); // Radius of the circle where the particle is standing float Perimeter = TWOPI * Radius; // Perimeter of that circle float ParticleSize = 0.5f * Perimeter; // Size of a single particle on that circle float ParticleLife = -1.0f - 4.0f * (1.0f - Normal.y); // Start with a negative life depending on height // DEBUG Generate on a plane for verification // Pos.x = 2.0f * (CellCenter.x - 0.5f); // Pos.y = 0.5f; // Pos.z = -2.0f * (CellCenter.y - 0.5f); // Normal.Set( 0, 1, 0 ); // Facing up // Tangent.Set( 1, 0, 0 ); // Right // ParticleSize = 1.0f;// / EFFECT_PARTICLES_COUNT; // Size of a single particle on that circle // DEBUG pScanlinePosition->R = Pos.x; pScanlinePosition->G = Pos.y; pScanlinePosition->B = Pos.z; pScanlinePosition->A = ParticleLife; pScanlineNormal->R = Normal.x; pScanlineNormal->G = Normal.y; pScanlineNormal->B = Normal.z; // pScanlineNormal->A = (0.025f + 0.002f) * EFFECT_PARTICLES_COUNT; // Half size + a little epsilon to make the tiles join correctly // pScanlineNormal->A = (0.1f + 0*0.002f) * EFFECT_PARTICLES_COUNT; // Half size + a little epsilon to make the tiles join correctly pScanlineNormal->A = ParticleSize; pScanlineTangent->R = Tangent.x; pScanlineTangent->G = Tangent.y; pScanlineTangent->B = Tangent.z; pScanlineTangent->A = Normal.y > 0.0f ? 1.0f : -1.0f; // Determines the particle's behavior... } delete[] pCellCenters; // Unfortunately, we need to create Textures to initialize our RenderTargets void* ppContentPositions[1]; ppContentPositions[0] = (void*) pInitialPositions; Texture2D* pTempPositions = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, ppContentPositions ); delete[] pInitialPositions; void* ppContentNormals[1]; ppContentNormals[0] = (void*) pInitialNormals; Texture2D* pTempNormals = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, ppContentNormals ); delete[] pInitialNormals; void* ppContentTangents[1]; ppContentTangents[0] = (void*) pInitialTangents; Texture2D* pTempTangents = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, ppContentTangents ); delete[] pInitialTangents; // Finally, create the render targets and initialize them m_ppRTParticlePositions[0] = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, NULL ); m_ppRTParticlePositions[1] = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, NULL ); m_ppRTParticlePositions[2] = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, NULL ); m_ppRTParticlePositions[0]->CopyFrom( *pTempPositions ); m_ppRTParticlePositions[1]->CopyFrom( *pTempPositions ); m_ppRTParticlePositions[2]->CopyFrom( *pTempPositions ); delete pTempPositions; m_ppRTParticleNormals[0] = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, NULL ); m_ppRTParticleNormals[1] = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, NULL ); m_ppRTParticleNormals[0]->CopyFrom( *pTempNormals ); m_ppRTParticleNormals[1]->CopyFrom( *pTempNormals ); delete pTempNormals; m_ppRTParticleTangents[0] = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, NULL ); m_ppRTParticleTangents[1] = new Texture2D( gs_Device, EFFECT_PARTICLES_COUNT, EFFECT_PARTICLES_COUNT, 1, PixelFormatRGBA32F::DESCRIPTOR, 1, NULL ); m_ppRTParticleTangents[0]->CopyFrom( *pTempTangents ); m_ppRTParticleTangents[1]->CopyFrom( *pTempTangents ); delete pTempTangents; ////////////////////////////////////////////////////////////////////////// // Create the constant buffers m_pCB_Render = new CB<CBRender>( gs_Device, 10 ); m_pCB_Render->m.DeltaTime.Set( 0, 1 ); }