void ShadowsDemo::onDraw() { App::onDraw(); const auto device = graphicsDevice(); device->setClearColor(0.0f, 0.0f, 0.0f, 0.0f); device->clear(ciri::ClearFlags::Color | ciri::ClearFlags::Depth); device->setRasterizerState(_rasterState); device->restoreDefaultBlendState(); if( _spotlightShader->isValid() && _directionalShader->isValid() ) { const cc::Mat4f& cameraViewProj = _camera.getProj() * _camera.getView(); bool firstLight = true; Light::Type boundLightType = Light::Type::Invalid; for( auto& light : _lights ) { // compute light matrices //const cc::Mat4f& lightView = light.view(); //const cc::Mat4f& lightProj = light.proj();//cc::math::perspectiveRH(45.0f, 1.0f, 0.1f, light.range());//light.proj(); //const cc::Mat4f lightViewProj = lightProj * lightView; if( light.type() == Light::Type::Directional ) { //light.computeViewProjFromFrustum(BoundingFrustum(cameraViewProj)); light.computeViewProjFromFrustum(BoundingFrustum(_camera.getFov(), _camera.getAspect(), _camera.getNearPlane(), _camera.getFarPlane(), _camera.getPosition(), _camera.getFpsFront(), _camera.getUp())); //light.computeViewProjOrtho(_camera.getView(), _camera.getFov(), _camera.getAspect(), _camera.getNearPlane(), _camera.getFarPlane()); } const cc::Mat4f lightViewProj = light.proj() * light.view(); if( light.castShadows() ) { device->setDepthStencilState(device->getDefaultDepthStencilDefault()); // set and clear render target ciri::IRenderTarget2D* depthTarget = _shadowTarget.get(); device->setRenderTargets(&depthTarget, 1); device->setClearColor(0.0f, 0.0f, 0.0f, 0.0f); device->clear(ciri::ClearFlags::Color | ciri::ClearFlags::Depth); // apply depth shader device->applyShader(_depthShader); // set viewport to depth size device->setViewport(ciri::Viewport(0, 0, _shadowTarget->getDepth()->getWidth(), _shadowTarget->getDepth()->getHeight())); // render all models for( auto& mdl : _models ) { _depthConstants.xform = lightViewProj * mdl->getXform().getWorld(); _depthConstantsBuffer->setData(sizeof(DepthConstants), &_depthConstants); device->setVertexBuffer(mdl->getVertexBuffer()); if( mdl->getIndexBuffer() != nullptr ) { device->setIndexBuffer(mdl->getIndexBuffer()); device->drawIndexed(ciri::PrimitiveTopology::TriangleList, mdl->getIndexBuffer()->getIndexCount()); } else { device->drawArrays(ciri::PrimitiveTopology::TriangleList, mdl->getVertexBuffer()->getVertexCount(), 0); } } // reser viewport to screen device->setViewport(ciri::Viewport(0, 0, window()->getWidth(), window()->getHeight())); // restore default render targets device->restoreDefaultRenderTargets(); } switch( light.type() ) { case Light::Type::Directional: { if( boundLightType != Light::Type::Directional || light.castShadows() ) { boundLightType = Light::Type::Directional; device->applyShader(_directionalShader); device->setTexture2D(0, _shadowTarget->getDepth(), ciri::ShaderStage::Pixel); device->setSamplerState(0, _shadowSampler, ciri::ShaderStage::Pixel); } _directionalConstants.LightDirection = light.direction(); _directionalConstants.LightColor = light.diffuseColor(); _directionalConstants.LightIntensity = light.diffuseIntensity(); _directionalConstants.campos = _camera.getPosition(); _directionalConstants.CastShadows = light.castShadows(); _directionalConstants.lightViewProj = lightViewProj; for( auto& mdl : _models ) { if( !mdl->isValid() ) { continue; } _directionalConstants.world = mdl->getXform().getWorld(); _directionalConstants.xform = cameraViewProj * _directionalConstants.world; _directionalConstantsBuffer->setData(sizeof(DirectionalConstants), &_directionalConstants); device->setVertexBuffer(mdl->getVertexBuffer()); if( mdl->getIndexBuffer() != nullptr ) { device->setIndexBuffer(mdl->getIndexBuffer()); device->drawIndexed(ciri::PrimitiveTopology::TriangleList, mdl->getIndexBuffer()->getIndexCount()); } else { device->drawArrays(ciri::PrimitiveTopology::TriangleList, mdl->getVertexBuffer()->getVertexCount(), 0); } } break; } case Light::Type::Spot: { if( boundLightType != Light::Type::Spot || light.castShadows() ) { boundLightType = Light::Type::Spot; device->applyShader(_spotlightShader); device->setTexture2D(0, _shadowTarget->getDepth(), ciri::ShaderStage::Pixel); device->setSamplerState(0, _shadowSampler, ciri::ShaderStage::Pixel); } _spotlightConstants.LightPosition = light.position(); _spotlightConstants.LightDirection = light.direction(); _spotlightConstants.LightColor = light.diffuseColor(); _spotlightConstants.LightCosInner = light.cosConeInnerAngle(true); _spotlightConstants.LightCosOuter = light.cosConeOuterAngle(true); _spotlightConstants.LightIntensity = light.diffuseIntensity(); _spotlightConstants.LightRange = light.range(); _spotlightConstants.CastShadows = light.castShadows(); _spotlightConstants.lightViewProj = lightViewProj; for( auto& mdl : _models ) { _spotlightConstants.world = mdl->getXform().getWorld(); _spotlightConstants.xform = cameraViewProj * _spotlightConstants.world; _spotlightConstantsBuffer->setData(sizeof(SpotlightConstants), &_spotlightConstants); device->setVertexBuffer(mdl->getVertexBuffer()); if( mdl->getIndexBuffer() != nullptr ) { device->setIndexBuffer(mdl->getIndexBuffer()); device->drawIndexed(ciri::PrimitiveTopology::TriangleList, mdl->getIndexBuffer()->getIndexCount()); } else { device->drawArrays(ciri::PrimitiveTopology::TriangleList, mdl->getVertexBuffer()->getVertexCount(), 0); } } break; } } if( firstLight ) { firstLight = false; device->setBlendState(_additiveBlendState); } } } device->present(); }
gl::Error StateManager11::syncFramebuffer(const gl::Framebuffer *framebuffer) { // Get the color render buffer and serial // Also extract the render target dimensions and view unsigned int renderTargetWidth = 0; unsigned int renderTargetHeight = 0; DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN; RenderTargetArray framebufferRTVs; bool missingColorRenderTarget = true; framebufferRTVs.fill(nullptr); const Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer); const gl::AttachmentList &colorbuffers = framebuffer11->getColorAttachmentsForRender(); for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment) { const gl::FramebufferAttachment *colorbuffer = colorbuffers[colorAttachment]; if (colorbuffer) { // the draw buffer must be either "none", "back" for the default buffer or the same // index as this color (in order) // check for zero-sized default framebuffer, which is a special case. // in this case we do not wish to modify any state and just silently return false. // this will not report any gl error but will cause the calling method to return. const gl::Extents &size = colorbuffer->getSize(); if (size.width == 0 || size.height == 0) { return gl::Error(GL_NO_ERROR); } // Extract the render target dimensions and view RenderTarget11 *renderTarget = NULL; gl::Error error = colorbuffer->getRenderTarget(&renderTarget); if (error.isError()) { return error; } ASSERT(renderTarget); framebufferRTVs[colorAttachment] = renderTarget->getRenderTargetView(); ASSERT(framebufferRTVs[colorAttachment]); if (missingColorRenderTarget) { renderTargetWidth = renderTarget->getWidth(); renderTargetHeight = renderTarget->getHeight(); renderTargetFormat = renderTarget->getDXGIFormat(); missingColorRenderTarget = false; } // Unbind render target SRVs from the shader here to prevent D3D11 warnings. if (colorbuffer->type() == GL_TEXTURE) { uintptr_t rtResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferRTVs[colorAttachment])); const gl::ImageIndex &index = colorbuffer->getTextureImageIndex(); // The index doesn't need to be corrected for the small compressed texture // workaround // because a rendertarget is never compressed. unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index); unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index); } } } // Get the depth stencil buffers ID3D11DepthStencilView *framebufferDSV = NULL; const gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer(); if (depthStencil) { RenderTarget11 *depthStencilRenderTarget = NULL; gl::Error error = depthStencil->getRenderTarget(&depthStencilRenderTarget); if (error.isError()) { return error; } ASSERT(depthStencilRenderTarget); framebufferDSV = depthStencilRenderTarget->getDepthStencilView(); ASSERT(framebufferDSV); // If there is no render buffer, the width, height and format values come from // the depth stencil if (missingColorRenderTarget) { renderTargetWidth = depthStencilRenderTarget->getWidth(); renderTargetHeight = depthStencilRenderTarget->getHeight(); } // Unbind render target SRVs from the shader here to prevent D3D11 warnings. if (depthStencil->type() == GL_TEXTURE) { uintptr_t depthStencilResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferDSV)); const gl::ImageIndex &index = depthStencil->getTextureImageIndex(); // The index doesn't need to be corrected for the small compressed texture workaround // because a rendertarget is never compressed. unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index); unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index); } } if (setRenderTargets(framebufferRTVs, framebufferDSV)) { setViewportBounds(renderTargetWidth, renderTargetHeight); } gl::Error error = framebuffer11->invalidateSwizzles(); if (error.isError()) { return error; } return gl::Error(GL_NO_ERROR); }