//[-------------------------------------------------------] //[ Private virtual PLRenderer::SurfacePainter functions ] //[-------------------------------------------------------] void SPRTTShaders::OnPaint(Surface &cSurface) { // Get the used renderer Renderer &cRenderer = GetRenderer(); // Clear the content of the current used render target by using gray (this way, in case on an graphics error we might still see at least something) cRenderer.Clear(Clear::Color | Clear::ZBuffer, Color4::Gray); // Backup current render target and set the new one to render in our texture buffer Surface *pRenderSurfaceBackup = cRenderer.GetRenderTarget(); if (cRenderer.SetRenderTarget(m_pRenderTarget)) { if (m_pColorTarget1) cRenderer.SetColorRenderTarget(static_cast<TextureBuffer*>(m_pColorTarget1), 1); if (m_pColorTarget2) cRenderer.SetColorRenderTarget(static_cast<TextureBuffer*>(m_pColorTarget2), 2); if (m_pColorTarget3) cRenderer.SetColorRenderTarget(static_cast<TextureBuffer*>(m_pColorTarget3), 3); // Draw the scene DrawScene(cRenderer); // Reset render target cRenderer.SetRenderTarget(pRenderSurfaceBackup); } // This code is similar to the code of the triangle sample. But instead of a // triangle we will draw three rotating quadrangles. Further the used vertex // buffer has texture coordinates and we apply the 'teapot' texture buffer on the primitives. // Clear the content of the current used render target // Make our program to the current one if (cRenderer.SetProgram(m_pProgram)) { // Set program vertex attributes, this creates a connection between "Vertex Buffer Attribute" and "Vertex Shader Attribute" m_pProgram->Set("VertexPosition", m_pPositionVertexBuffer, VertexBuffer::Position); m_pProgram->Set("VertexTextureCoordinate", m_pPositionVertexBuffer, VertexBuffer::TexCoord); m_pProgram->Set("VertexColor", m_pColorVertexBuffer, VertexBuffer::Color); // Set color factor m_pProgram->Set("ColorFactor", 0.0f); // Calculate the composed view projection matrix - we need it multiple times Matrix4x4 mViewProjection; { // Calculate the view matrix Matrix4x4 mView; { mView.SetTranslation(0.0f, 0.0f, -5.0f); } // Calculate the projection matrix Matrix4x4 mProjection; { const float fAspect = 1.0f; const float fAspectRadio = cRenderer.GetViewport().GetWidth()/(cRenderer.GetViewport().GetHeight()*fAspect); mProjection.PerspectiveFov(static_cast<float>(45.0f*Math::DegToRad), fAspectRadio, 0.001f, 1000.0f); } // Calculate the composed view projection matrix mViewProjection = mProjection*mView; } // No back face culling, please. Else we can only see one 'side' of the quadrangle cRenderer.SetRenderState(RenderState::CullMode, Cull::None); Matrix4x4 mWorld; { // Draw quadrangle 1: Primary render target // Set object space to clip space matrix uniform ProgramUniform *pProgramUniform = m_pProgram->GetUniform("ObjectSpaceToClipSpaceMatrix"); if (pProgramUniform) { mWorld.SetTranslationMatrix(2.0f, 1.0f, 0.0f); pProgramUniform->Set(mViewProjection*mWorld); } { // Set the texture buffer we rendered our teapot in as the current texture buffer const int nTextureUnit = m_pProgram->Set("DiffuseMap", m_pRenderTarget->GetTextureBuffer()); if (nTextureUnit >= 0) { // Disable mip mapping - this is required because we created/filled no mipmaps for your texture buffer cRenderer.SetSamplerState(nTextureUnit, Sampler::MagFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MinFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MipFilter, TextureFiltering::None); } } // Draw cRenderer.DrawPrimitives(Primitive::TriangleStrip, 0, 4); } { // Draw quadrangle 2: Color render target 1 // Set object space to clip space matrix uniform ProgramUniform *pProgramUniform = m_pProgram->GetUniform("ObjectSpaceToClipSpaceMatrix"); if (pProgramUniform) { mWorld.FromEulerAngleY(static_cast<float>(m_fRotation*Math::DegToRad)); mWorld.SetTranslation(-2.0f, 1.0f, 0.0f); pProgramUniform->Set(mViewProjection*mWorld); } { // Set the texture buffer we rendered our teapot in as the current texture buffer const int nTextureUnit = m_pProgram->Set("DiffuseMap", m_pColorTarget1 ? static_cast<TextureBuffer*>(m_pColorTarget1) : m_pRenderTarget->GetTextureBuffer()); if (nTextureUnit >= 0) { // Disable mip mapping - this is required because we created/filled no mipmaps for your texture buffer cRenderer.SetSamplerState(nTextureUnit, Sampler::MagFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MinFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MipFilter, TextureFiltering::None); } } // Draw cRenderer.DrawPrimitives(Primitive::TriangleStrip, 0, 4); } { // Draw quadrangle 3: Color render target 2 // Set object space to clip space matrix uniform ProgramUniform *pProgramUniform = m_pProgram->GetUniform("ObjectSpaceToClipSpaceMatrix"); if (pProgramUniform) { mWorld.FromEulerAngleZ(static_cast<float>(m_fRotation*Math::DegToRad)); mWorld.SetTranslation(0.0f, 1.0f, 0.0f); pProgramUniform->Set(mViewProjection*mWorld); } { // Set the texture buffer we rendered our teapot in as the current texture buffer const int nTextureUnit = m_pProgram->Set("DiffuseMap", m_pColorTarget2 ? static_cast<TextureBuffer*>(m_pColorTarget2) : m_pRenderTarget->GetTextureBuffer()); if (nTextureUnit >= 0) { // Disable mip mapping - this is required because we created/filled no mipmaps for your texture buffer cRenderer.SetSamplerState(nTextureUnit, Sampler::MagFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MinFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MipFilter, TextureFiltering::None); } } // Draw cRenderer.DrawPrimitives(Primitive::TriangleStrip, 0, 4); } { // Draw quadrangle 4: Color render target 3 // Set object space to clip space matrix uniform ProgramUniform *pProgramUniform = m_pProgram->GetUniform("ObjectSpaceToClipSpaceMatrix"); if (pProgramUniform) { mWorld.FromEulerAngleZ(static_cast<float>(-m_fRotation*Math::DegToRad)); mWorld.SetTranslation(-2.0f, -1.0f, 0.0f); pProgramUniform->Set(mViewProjection*mWorld); } { // Set the texture buffer we rendered our teapot in as the current texture buffer const int nTextureUnit = m_pProgram->Set("DiffuseMap", m_pColorTarget3 ? static_cast<TextureBuffer*>(m_pColorTarget3) : m_pRenderTarget->GetTextureBuffer()); if (nTextureUnit >= 0) { // Disable mip mapping - this is required because we created/filled no mipmaps for your texture buffer cRenderer.SetSamplerState(nTextureUnit, Sampler::MagFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MinFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MipFilter, TextureFiltering::None); } } // Draw cRenderer.DrawPrimitives(Primitive::TriangleStrip, 0, 4); } { // Draw quadrangle 4: Primary render target, but with per vertex color - the primitive will be quite colorful :) // Set object space to clip space matrix uniform ProgramUniform *pProgramUniform = m_pProgram->GetUniform("ObjectSpaceToClipSpaceMatrix"); if (pProgramUniform) { mWorld.FromEulerAngleZ(static_cast<float>(-m_fRotation*Math::DegToRad)); mWorld.SetTranslation(2.0f, -1.0f, 0.0f); pProgramUniform->Set(mViewProjection*mWorld); } // Set color factor m_pProgram->Set("ColorFactor", 1.0f); { // Set the texture buffer we rendered our teapot in as the current texture buffer const int nTextureUnit = m_pProgram->Set("DiffuseMap", m_pRenderTarget->GetTextureBuffer()); if (nTextureUnit >= 0) { // Disable mip mapping - this is required because we created/filled no mipmaps for your texture buffer cRenderer.SetSamplerState(nTextureUnit, Sampler::MagFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MinFilter, TextureFiltering::Linear); cRenderer.SetSamplerState(nTextureUnit, Sampler::MipFilter, TextureFiltering::None); } } // Draw cRenderer.DrawPrimitives(Primitive::TriangleStrip, 0, 4); } // Change the backface culling back to the default setting cRenderer.SetRenderState(RenderState::CullMode, Cull::CCW); } // Increase the rotation by the current time difference (time past since the last frame) // -> Normally, such work should NOT be performed within the rendering step, but we want // to keep the implementation simple in here... m_fRotation += Timing::GetInstance()->GetTimeDifference()*50; }