Esempio n. 1
0
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();
}
Esempio n. 2
0
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);
}