Пример #1
0
void HsvFeatures::UpdateFeatureVector(const Sample &s)
{
    IntRect rect = s.GetROI();
    cv::Rect roi(rect.XMin(), rect.YMin(), rect.Width(), rect.Height());

    m_featVec.setZero();
    cv::Mat hsv_img = s.GetImage().GetHsvImage()(roi);

    int height = rect.Height();
    int width = rect.Width();

    // continuous?
    if(hsv_img.isContinuous())
    {
        width *= height;
        height = 1;
    }

    int ix, iy;
    uchar *p;
    for(iy=0; iy < height; ++iy)
    {
        p = hsv_img.ptr<uchar>(iy);

        for(ix=0; ix < width; ++ix)
        {
            cv::Vec3b pixel(p[3*ix+0], p[3*ix+1], p[3*ix+2]);
            auto bin_idx = compBinIdx(pixel);
            m_featVec[bin_idx]++;
        }
    }

    m_featVec /= rect.Area();

}
    void D3D9Blit(const IntRect& dstRect, unsigned char* src, unsigned srcStride, bool discard = false)
    {
        RECT d3dRect;

        d3dRect.left = dstRect.left_;
        d3dRect.top = dstRect.top_;
        d3dRect.right = dstRect.right_;
        d3dRect.bottom = dstRect.bottom_;

        int level = 0;
        DWORD flags = discard ? D3DLOCK_DISCARD : 0;

        D3DLOCKED_RECT d3dLockedRect;
        IDirect3DTexture9* object = (IDirect3DTexture9*) webTexture2D_->GetTexture2D()->GetGPUObject();

        if (FAILED(object->LockRect(level, &d3dLockedRect, (flags & D3DLOCK_DISCARD) ? 0 : &d3dRect, flags)))
        {
            LOGERROR("WebTexture2D - Could not lock texture");
            return;
        }

        int width = dstRect.Width();
        int height = dstRect.Height();

        for (int j = 0; j < height; ++j)
        {
            unsigned char* dst = (unsigned char*) d3dLockedRect.pBits + j * d3dLockedRect.Pitch;
            memcpy(dst, src, width * 4);
            src += srcStride;
        }

        object->UnlockRect(level);
    }
Пример #3
0
BRegion&
View::_ScreenClipping(BRegion* windowContentClipping, bool force) const
{
    if (!fScreenClippingValid || force) {
        fScreenClipping = fLocalClipping;
        ConvertToScreen(&fScreenClipping);

        // see if parts of our bounds are hidden underneath
        // the parent, the local clipping does not account for this
        IntRect clippedBounds = Bounds();
        ConvertToVisibleInTopView(&clippedBounds);
        if (clippedBounds.Width() < fScreenClipping.Frame().Width()
                || clippedBounds.Height() < fScreenClipping.Frame().Height()) {
            BRegion* temp = fWindow->GetRegion();
            if (temp) {
                temp->Set((clipping_rect)clippedBounds);
                fScreenClipping.IntersectWith(temp);
                fWindow->RecycleRegion(temp);
            }
        }

        fScreenClipping.IntersectWith(windowContentClipping);
        fScreenClippingValid = true;
    }

    return fScreenClipping;
}
Ray SceneView3D::GetCameraRay()
{
    Ray camRay;

    Input* input = GetSubsystem<Input>();
    IntVector2 cpos = input->GetMousePosition();

    IntRect rect = GetRect();

    if (!rect.Width() || !rect.Height())
        return camRay;

    int x = rect.left_;
    int y = rect.top_;
    GetInternalWidget()->ConvertToRoot(x, y);

    return  camera_->GetScreenRay(float(cpos.x_ - x) / rect.Width(),
                                  float(cpos.y_ - y) / rect.Height());
}
Пример #5
0
bool PreviewTab::RenderWindowContent()
{
    if (GetSubsystem<SceneManager>()->GetActiveScene() == nullptr)
        return true;

    IntRect rect = UpdateViewRect();
    ui::Image(view_.Get(), ImVec2{static_cast<float>(rect.Width()), static_cast<float>(rect.Height())});
    if (!inputGrabbed_ && simulationStatus_ == SCENE_SIMULATION_RUNNING && ui::IsItemHovered() &&
        ui::IsAnyMouseDown() && GetInput()->IsMouseVisible())
        GrabInput();

    return true;
}
Пример #6
0
IntRect PreviewTab::UpdateViewRect()
{
    IntRect tabRect = BaseClassName::UpdateViewRect();
    if (viewRect_ != tabRect)
    {
        viewRect_ = tabRect;
        view_->SetSize(tabRect.Width(), tabRect.Height(), Graphics::GetRGBFormat(), TEXTURE_RENDERTARGET);
        view_->GetRenderSurface()->SetUpdateMode(SURFACE_UPDATEALWAYS);
        static_cast<RootUIElement*>(GetUI()->GetRoot())->SetOffset(tabRect.Min());
        UpdateViewports();
    }
    return tabRect;
}
Пример #7
0
bool SpriteSheet2D::EndLoadFromPListFile()
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();
    texture_ = cache->GetResource<Texture2D>(loadTextureName_);
    if (!texture_)
    {
        LOGERROR("Could not load texture " + loadTextureName_);
        loadXMLFile_.Reset();
        loadTextureName_.Clear();
        return false;
    }

    const PListValueMap& root = loadPListFile_->GetRoot();

    const PListValueMap& frames = root["frames"].GetValueMap();
    for (PListValueMap::ConstIterator i = frames.Begin(); i != frames.End(); ++i)
    {
        String name = i->first_.Split('.')[0];

        const PListValueMap& frameInfo = i->second_.GetValueMap();
        if (frameInfo["rotated"].GetBool())
        {
            LOGWARNING("Rotated sprite is not support now");
            continue;
        }

        IntRect rectangle = frameInfo["frame"].GetIntRect();
        Vector2 hotSpot(0.5f, 0.5f);
        IntVector2 offset(0, 0);

        IntRect sourceColorRect = frameInfo["sourceColorRect"].GetIntRect();
        if (sourceColorRect.left_ != 0 && sourceColorRect.top_ != 0)
        {
            offset.x_ = -sourceColorRect.left_;
            offset.y_ = -sourceColorRect.top_;

            IntVector2 sourceSize = frameInfo["sourceSize"].GetIntVector2();
            hotSpot.x_ = ((float)offset.x_ + sourceSize.x_ / 2) / rectangle.Width();
            hotSpot.y_ = 1.0f - ((float)offset.y_ + sourceSize.y_/ 2) / rectangle.Height();
        }

        DefineSprite(name, rectangle, hotSpot, offset);
    }

    loadXMLFile_.Reset();
    loadTextureName_.Clear();
    return true;
}
Пример #8
0
void
FilterNodeD2D1::SetAttribute(uint32_t aIndex, const IntRect &aValue)
{
  if (mType == FilterType::TURBULENCE) {
    MOZ_ASSERT(aIndex == ATT_TURBULENCE_RECT);

    mEffect->SetValue(D2D1_TURBULENCE_PROP_OFFSET, D2D1::Vector2F(Float(aValue.X()), Float(aValue.Y())));
    mEffect->SetValue(D2D1_TURBULENCE_PROP_SIZE, D2D1::Vector2F(Float(aValue.Width()), Float(aValue.Height())));
    return;
  }

  UINT32 input = GetD2D1PropForAttribute(mType, aIndex);
  MOZ_ASSERT(input < mEffect->GetPropertyCount());

  mEffect->SetValue(input, D2D1::RectF(Float(aValue.X()), Float(aValue.Y()),
                                       Float(aValue.XMost()), Float(aValue.YMost())));
}
Пример #9
0
void RawFeatures::UpdateFeatureVector(const Sample& s)
{
	IntRect rect = s.GetROI(); // note this truncates to integers
	cv::Rect roi(rect.XMin(), rect.YMin(), rect.Width(), rect.Height());
	cv::resize(s.GetImage().GetImage(0)(roi), m_patchImage, m_patchImage.size());
	//equalizeHist(m_patchImage, m_patchImage);
	
	int ind = 0;
	for (int i = 0; i < kPatchSize; ++i)
	{
		uchar* pixel = m_patchImage.ptr(i);
		for (int j = 0; j < kPatchSize; ++j, ++pixel, ++ind)
		{
			m_featVec[ind] = ((double)*pixel)/255;
		}
	}
}
Пример #10
0
void IntRect::Merge(const IntRect& rect)
{
    if (Width() <= 0 || Height() <= 0)
    {
        *this = rect;
    }
    else if (rect.Width() > 0 && rect.Height() > 0)
    {
        if (rect.left_ < left_)
            left_ = rect.left_;
        if (rect.top_ < top_)
            top_ = rect.top_;
        if (rect.right_ > right_)
            right_ = rect.right_;
        if (rect.bottom_ > bottom_)
            bottom_ = rect.bottom_;
    }
}
Пример #11
0
void LaRank::Update(const MultiSample& sample, int y)
{
	// add new support pattern
	SupportPattern* sp = new SupportPattern;
	const vector<FloatRect>& rects = sample.GetRects();
	FloatRect centre = rects[y];
	for (int i = 0; i < (int)rects.size(); ++i)
	{
		// express r in coord frame of centre sample
		FloatRect r = rects[i];
		r.Translate(-centre.XMin(), -centre.YMin());
		sp->yv.push_back(r);
		if (!m_config.quietMode && m_config.debugMode)
		{
			// store a thumbnail for each sample
			Mat im(kTileSize, kTileSize, CV_8UC1);
			IntRect rect = rects[i];
			cv::Rect roi(rect.XMin(), rect.YMin(), rect.Width(), rect.Height());
			cv::resize(sample.GetImage().GetImage(0)(roi), im, im.size());
			sp->images.push_back(im);
		}
	}
	// evaluate features for each sample
	sp->x.resize(rects.size());
	const_cast<Features&>(m_features).Eval(sample, sp->x);
	sp->y = y;
	sp->refCount = 0;
	m_sps.push_back(sp);

	ProcessNew((int)m_sps.size()-1);
	BudgetMaintenance();
	
	for (int i = 0; i < 10; ++i)
	{
		Reprocess();
		BudgetMaintenance();
	}
}
Пример #12
0
void
View::ParentResized(int32 x, int32 y, BRegion* dirtyRegion)
{
    IntRect newFrame = fFrame;
    resize_frame(newFrame, fResizeMode & 0x0000ffff, x, y);

    if (newFrame != fFrame) {
        // careful, MoveBy will change fFrame
        int32 widthDiff = (int32)(newFrame.Width() - fFrame.Width());
        int32 heightDiff = (int32)(newFrame.Height() - fFrame.Height());

        MoveBy(newFrame.left - fFrame.left,
               newFrame.top - fFrame.top, dirtyRegion);

        ResizeBy(widthDiff, heightDiff, dirtyRegion);
    } else {
        // TODO: this covers the fact that our screen clipping might change
        // when the parent changes its size, even though our frame stays
        // the same - there might be a way to test for this, but axeld doesn't
        // know, stippi should look into this when he's back :)
        InvalidateScreenClipping();
    }
}
Пример #13
0
void Batch::Prepare(View* view, bool setModelTransform) const
{
    if (!vertexShader_ || !pixelShader_)
        return;
    
    Graphics* graphics = view->GetGraphics();
    Renderer* renderer = view->GetRenderer();
    Node* cameraNode = camera_ ? camera_->GetNode() : 0;
    Light* light = lightQueue_ ? lightQueue_->light_ : 0;
    Texture2D* shadowMap = lightQueue_ ? lightQueue_->shadowMap_ : 0;

    // Set pass / material-specific renderstates
    if (pass_ && material_)
    {
        bool isShadowPass = pass_->GetType() == PASS_SHADOW;
        
        BlendMode blend = pass_->GetBlendMode();
        // Turn additive blending into subtract if the light is negative
        if (light && light->IsNegative())
        {
            if (blend == BLEND_ADD)
                blend = BLEND_SUBTRACT;
            else if (blend == BLEND_ADDALPHA)
                blend = BLEND_SUBTRACTALPHA;
        }
        
        graphics->SetBlendMode(blend);
        renderer->SetCullMode(isShadowPass ? material_->GetShadowCullMode() : material_->GetCullMode(), camera_);
        if (!isShadowPass)
        {
            const BiasParameters& depthBias = material_->GetDepthBias();
            graphics->SetDepthBias(depthBias.constantBias_, depthBias.slopeScaledBias_);
        }
        graphics->SetDepthTest(pass_->GetDepthTestMode());
        graphics->SetDepthWrite(pass_->GetDepthWrite());
    }
    
    // Set shaders first. The available shader parameters and their register/uniform positions depend on the currently set shaders
    graphics->SetShaders(vertexShader_, pixelShader_);
    
    // Set global (per-frame) shader parameters
    if (graphics->NeedParameterUpdate(SP_FRAME, (void*)0))
        view->SetGlobalShaderParameters();
    
    // Set camera shader parameters
    unsigned cameraHash = overrideView_ ? (unsigned)(size_t)camera_ + 4 : (unsigned)(size_t)camera_;
    if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<void*>(cameraHash)))
        view->SetCameraShaderParameters(camera_, true, overrideView_);
    
    // Set viewport shader parameters
    IntVector2 rtSize = graphics->GetRenderTargetDimensions();
    IntRect viewport = graphics->GetViewport();
    unsigned viewportHash = (viewport.left_) | (viewport.top_ << 8) | (viewport.right_ << 16) | (viewport.bottom_ << 24);
    
    if (graphics->NeedParameterUpdate(SP_VIEWPORT, reinterpret_cast<void*>(viewportHash)))
    {
        float rtWidth = (float)rtSize.x_;
        float rtHeight = (float)rtSize.y_;
        float widthRange = 0.5f * viewport.Width() / rtWidth;
        float heightRange = 0.5f * viewport.Height() / rtHeight;
        
        #ifdef URHO3D_OPENGL
        Vector4 bufferUVOffset(((float)viewport.left_) / rtWidth + widthRange,
            1.0f - (((float)viewport.top_) / rtHeight + heightRange), widthRange, heightRange);
        #else
        Vector4 bufferUVOffset((0.5f + (float)viewport.left_) / rtWidth + widthRange,
            (0.5f + (float)viewport.top_) / rtHeight + heightRange, widthRange, heightRange);
        #endif
        graphics->SetShaderParameter(VSP_GBUFFEROFFSETS, bufferUVOffset);
        
        float sizeX = 1.0f / rtWidth;
        float sizeY = 1.0f / rtHeight;
        graphics->SetShaderParameter(PSP_GBUFFERINVSIZE, Vector4(sizeX, sizeY, 0.0f, 0.0f));
    }
    
    // Set model or skinning transforms
    if (setModelTransform && graphics->NeedParameterUpdate(SP_OBJECTTRANSFORM, worldTransform_))
    {
        if (geometryType_ == GEOM_SKINNED)
        {
            graphics->SetShaderParameter(VSP_SKINMATRICES, reinterpret_cast<const float*>(worldTransform_), 
                12 * numWorldTransforms_);
        }
        else
            graphics->SetShaderParameter(VSP_MODEL, *worldTransform_);
        
        // Set the orientation for billboards, either from the object itself or from the camera
        if (geometryType_ == GEOM_BILLBOARD)
        {
            if (numWorldTransforms_ > 1)
                graphics->SetShaderParameter(VSP_BILLBOARDROT, worldTransform_[1].RotationMatrix());
            else
                graphics->SetShaderParameter(VSP_BILLBOARDROT, cameraNode->GetWorldRotation().RotationMatrix());
        }
    }
    
    // Set zone-related shader parameters
    BlendMode blend = graphics->GetBlendMode();
    // If the pass is additive, override fog color to black so that shaders do not need a separate additive path
    bool overrideFogColorToBlack = blend == BLEND_ADD || blend == BLEND_ADDALPHA;
    unsigned zoneHash = (unsigned)(size_t)zone_;
    if (overrideFogColorToBlack)
        zoneHash += 0x80000000;
    if (zone_ && graphics->NeedParameterUpdate(SP_ZONE, reinterpret_cast<void*>(zoneHash)))
    {
        graphics->SetShaderParameter(VSP_AMBIENTSTARTCOLOR, zone_->GetAmbientStartColor());
        graphics->SetShaderParameter(VSP_AMBIENTENDCOLOR, zone_->GetAmbientEndColor().ToVector4() - zone_->GetAmbientStartColor().ToVector4());
        
        const BoundingBox& box = zone_->GetBoundingBox();
        Vector3 boxSize = box.Size();
        Matrix3x4 adjust(Matrix3x4::IDENTITY);
        adjust.SetScale(Vector3(1.0f / boxSize.x_, 1.0f / boxSize.y_, 1.0f / boxSize.z_));
        adjust.SetTranslation(Vector3(0.5f, 0.5f, 0.5f));
        Matrix3x4 zoneTransform = adjust * zone_->GetInverseWorldTransform();
        graphics->SetShaderParameter(VSP_ZONE, zoneTransform);
        
        graphics->SetShaderParameter(PSP_AMBIENTCOLOR, zone_->GetAmbientColor());
        graphics->SetShaderParameter(PSP_FOGCOLOR, overrideFogColorToBlack ? Color::BLACK : zone_->GetFogColor());
        
        float farClip = camera_->GetFarClip();
        float fogStart = Min(zone_->GetFogStart(), farClip);
        float fogEnd = Min(zone_->GetFogEnd(), farClip);
        if (fogStart >= fogEnd * (1.0f - M_LARGE_EPSILON))
            fogStart = fogEnd * (1.0f - M_LARGE_EPSILON);
        float fogRange = Max(fogEnd - fogStart, M_EPSILON);
        Vector4 fogParams(fogEnd / farClip, farClip / fogRange, 0.0f, 0.0f);
        
        Node* zoneNode = zone_->GetNode();
        if (zone_->GetHeightFog() && zoneNode)
        {
            Vector3 worldFogHeightVec = zoneNode->GetWorldTransform() * Vector3(0.0f, zone_->GetFogHeight(), 0.0f);
            fogParams.z_ = worldFogHeightVec.y_;
            fogParams.w_ = zone_->GetFogHeightScale() / Max(zoneNode->GetWorldScale().y_, M_EPSILON);
        }
        
        graphics->SetShaderParameter(PSP_FOGPARAMS, fogParams);
    }
    
    // Set light-related shader parameters
    if (lightQueue_)
    {
        if (graphics->NeedParameterUpdate(SP_VERTEXLIGHTS, lightQueue_) && graphics->HasShaderParameter(VS, VSP_VERTEXLIGHTS))
        {
            Vector4 vertexLights[MAX_VERTEX_LIGHTS * 3];
            const PODVector<Light*>& lights = lightQueue_->vertexLights_;
            
            for (unsigned i = 0; i < lights.Size(); ++i)
            {
                Light* vertexLight = lights[i];
                Node* vertexLightNode = vertexLight->GetNode();
                LightType type = vertexLight->GetLightType();
                
                // Attenuation
                float invRange, cutoff, invCutoff;
                if (type == LIGHT_DIRECTIONAL)
                    invRange = 0.0f;
                else
                    invRange = 1.0f / Max(vertexLight->GetRange(), M_EPSILON);
                if (type == LIGHT_SPOT)
                {
                    cutoff = Cos(vertexLight->GetFov() * 0.5f);
                    invCutoff = 1.0f / (1.0f - cutoff);
                }
                else
                {
                    cutoff = -1.0f;
                    invCutoff = 1.0f;
                }
                
                // Color
                float fade = 1.0f;
                float fadeEnd = vertexLight->GetDrawDistance();
                float fadeStart = vertexLight->GetFadeDistance();
                
                // Do fade calculation for light if both fade & draw distance defined
                if (vertexLight->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
                    fade = Min(1.0f - (vertexLight->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);
                
                Color color = vertexLight->GetEffectiveColor() * fade;
                vertexLights[i * 3] = Vector4(color.r_, color.g_, color.b_, invRange);
                
                // Direction
                vertexLights[i * 3 + 1] = Vector4(-(vertexLightNode->GetWorldDirection()), cutoff);
                
                // Position
                vertexLights[i * 3 + 2] = Vector4(vertexLightNode->GetWorldPosition(), invCutoff);
            }
            
            if (lights.Size())
                graphics->SetShaderParameter(VSP_VERTEXLIGHTS, vertexLights[0].Data(), lights.Size() * 3 * 4);
        }
    }
    
    if (light && graphics->NeedParameterUpdate(SP_LIGHT, light))
    {
        // Deferred light volume batches operate in a camera-centered space. Detect from material, zone & pass all being null
        bool isLightVolume = !material_ && !pass_ && !zone_;
        
        Matrix3x4 cameraEffectiveTransform = camera_->GetEffectiveWorldTransform();
        Vector3 cameraEffectivePos = cameraEffectiveTransform.Translation();

        Node* lightNode = light->GetNode();
        Matrix3 lightWorldRotation = lightNode->GetWorldRotation().RotationMatrix();
        
        graphics->SetShaderParameter(VSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
        
        float atten = 1.0f / Max(light->GetRange(), M_EPSILON);
        graphics->SetShaderParameter(VSP_LIGHTPOS, Vector4(lightNode->GetWorldPosition(), atten));
        
        if (graphics->HasShaderParameter(VS, VSP_LIGHTMATRICES))
        {
            switch (light->GetLightType())
            {
            case LIGHT_DIRECTIONAL:
                {
                    Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
                    unsigned numSplits = lightQueue_->shadowSplits_.Size();
                    for (unsigned i = 0; i < numSplits; ++i)
                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, Vector3::ZERO);
                    
                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
                }
                break;
                
            case LIGHT_SPOT:
                {
                    Matrix4 shadowMatrices[2];
                    
                    CalculateSpotMatrix(shadowMatrices[0], light, Vector3::ZERO);
                    bool isShadowed = shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP);
                    if (isShadowed)
                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, Vector3::ZERO);
                    
                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
                }
                break;
                
            case LIGHT_POINT:
                {
                    Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
                    // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
                    // the next parameter
                    #ifdef URHO3D_OPENGL
                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 16);
                    #else
                    graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 12);
                    #endif
                }
                break;
            }
        }
        
        float fade = 1.0f;
        float fadeEnd = light->GetDrawDistance();
        float fadeStart = light->GetFadeDistance();
        
        // Do fade calculation for light if both fade & draw distance defined
        if (light->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
            fade = Min(1.0f - (light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);
        
        // Negative lights will use subtract blending, so write absolute RGB values to the shader parameter
        graphics->SetShaderParameter(PSP_LIGHTCOLOR, Color(light->GetEffectiveColor().Abs(),
            light->GetEffectiveSpecularIntensity()) * fade);
        graphics->SetShaderParameter(PSP_LIGHTDIR, lightWorldRotation * Vector3::BACK);
        graphics->SetShaderParameter(PSP_LIGHTPOS, Vector4((isLightVolume ? (lightNode->GetWorldPosition() -
            cameraEffectivePos) : lightNode->GetWorldPosition()), atten));
        
        if (graphics->HasShaderParameter(PS, PSP_LIGHTMATRICES))
        {
            switch (light->GetLightType())
            {
            case LIGHT_DIRECTIONAL:
                {
                    Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
                    unsigned numSplits = lightQueue_->shadowSplits_.Size();
                    for (unsigned i = 0; i < numSplits; ++i)
                    {
                        CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer, isLightVolume ? cameraEffectivePos :
                            Vector3::ZERO);
                    }
                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
                }
                break;
                
            case LIGHT_SPOT:
                {
                    Matrix4 shadowMatrices[2];
                    
                    CalculateSpotMatrix(shadowMatrices[0], light, cameraEffectivePos);
                    bool isShadowed = lightQueue_->shadowMap_ != 0;
                    if (isShadowed)
                    {
                        CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer, isLightVolume ? cameraEffectivePos :
                            Vector3::ZERO);
                    }
                    
                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
                }
                break;
                
            case LIGHT_POINT:
                {
                    Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
                    // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
                    // the next parameter
                    #ifdef URHO3D_OPENGL
                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 16);
                    #else
                    graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 12);
                    #endif
                }
                break;
            }
        }
        
        // Set shadow mapping shader parameters
        if (shadowMap)
        {
            {
                // Calculate point light shadow sampling offsets (unrolled cube map)
                unsigned faceWidth = shadowMap->GetWidth() / 2;
                unsigned faceHeight = shadowMap->GetHeight() / 3;
                float width = (float)shadowMap->GetWidth();
                float height = (float)shadowMap->GetHeight();
                #ifdef URHO3D_OPENGL
                    float mulX = (float)(faceWidth - 3) / width;
                    float mulY = (float)(faceHeight - 3) / height;
                    float addX = 1.5f / width;
                    float addY = 1.5f / height;
                #else
                    float mulX = (float)(faceWidth - 4) / width;
                    float mulY = (float)(faceHeight - 4) / height;
                    float addX = 2.5f / width;
                    float addY = 2.5f / height;
                #endif
                // If using 4 shadow samples, offset the position diagonally by half pixel
                if (renderer->GetShadowQuality() & SHADOWQUALITY_HIGH_16BIT)
                {
                    addX -= 0.5f / width;
                    addY -= 0.5f / height;
                }
                graphics->SetShaderParameter(PSP_SHADOWCUBEADJUST, Vector4(mulX, mulY, addX, addY));
            }
            
            {
                // Calculate shadow camera depth parameters for point light shadows and shadow fade parameters for
                //  directional light shadows, stored in the same uniform
                Camera* shadowCamera = lightQueue_->shadowSplits_[0].shadowCamera_;
                float nearClip = shadowCamera->GetNearClip();
                float farClip = shadowCamera->GetFarClip();
                float q = farClip / (farClip - nearClip);
                float r = -q * nearClip;
                
                const CascadeParameters& parameters = light->GetShadowCascade();
                float viewFarClip = camera_->GetFarClip();
                float shadowRange = parameters.GetShadowRange();
                float fadeStart = parameters.fadeStart_ * shadowRange / viewFarClip;
                float fadeEnd = shadowRange / viewFarClip;
                float fadeRange = fadeEnd - fadeStart;
                
                graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeStart, 1.0f / fadeRange));
            }
            
            {
                float intensity = light->GetShadowIntensity();
                float fadeStart = light->GetShadowFadeDistance();
                float fadeEnd = light->GetShadowDistance();
                if (fadeStart > 0.0f && fadeEnd > 0.0f && fadeEnd > fadeStart)
                    intensity = Lerp(intensity, 1.0f, Clamp((light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f));
                float pcfValues = (1.0f - intensity);
                float samples = renderer->GetShadowQuality() >= SHADOWQUALITY_HIGH_16BIT ? 4.0f : 1.0f;

                graphics->SetShaderParameter(PSP_SHADOWINTENSITY, Vector4(pcfValues / samples, intensity, 0.0f, 0.0f));
            }
            
            float sizeX = 1.0f / (float)shadowMap->GetWidth();
            float sizeY = 1.0f / (float)shadowMap->GetHeight();
            graphics->SetShaderParameter(PSP_SHADOWMAPINVSIZE, Vector4(sizeX, sizeY, 0.0f, 0.0f));
            
            Vector4 lightSplits(M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE);
            if (lightQueue_->shadowSplits_.Size() > 1)
                lightSplits.x_ = lightQueue_->shadowSplits_[0].farSplit_ / camera_->GetFarClip();
            if (lightQueue_->shadowSplits_.Size() > 2)
                lightSplits.y_ = lightQueue_->shadowSplits_[1].farSplit_ / camera_->GetFarClip();
            if (lightQueue_->shadowSplits_.Size() > 3)
                lightSplits.z_ = lightQueue_->shadowSplits_[2].farSplit_ / camera_->GetFarClip();
            
            graphics->SetShaderParameter(PSP_SHADOWSPLITS, lightSplits);
        }
    }
    
    // Set material-specific shader parameters and textures
    if (material_)
    {
        if (graphics->NeedParameterUpdate(SP_MATERIAL, material_))
        {
            // Update shader parameter animations
            material_->UpdateShaderParameterAnimations();

            const HashMap<StringHash, MaterialShaderParameter>& parameters = material_->GetShaderParameters();
            for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator i = parameters.Begin(); i != parameters.End(); ++i)
                graphics->SetShaderParameter(i->first_, i->second_.value_);
        }
        
        const SharedPtr<Texture>* textures = material_->GetTextures();
        for (unsigned i = 0; i < MAX_MATERIAL_TEXTURE_UNITS; ++i)
        {
            TextureUnit unit = (TextureUnit)i;
            if (textures[i] && graphics->HasTextureUnit(unit))
                graphics->SetTexture(i, textures[i]);
        }
    }
    
    // Set light-related textures
    if (light)
    {
        if (shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP))
            graphics->SetTexture(TU_SHADOWMAP, shadowMap);
        if (graphics->HasTextureUnit(TU_LIGHTRAMP))
        {
            Texture* rampTexture = light->GetRampTexture();
            if (!rampTexture)
                rampTexture = renderer->GetDefaultLightRamp();
            graphics->SetTexture(TU_LIGHTRAMP, rampTexture);
        }
        if (graphics->HasTextureUnit(TU_LIGHTSHAPE))
        {
            Texture* shapeTexture = light->GetShapeTexture();
            if (!shapeTexture && light->GetLightType() == LIGHT_SPOT)
                shapeTexture = renderer->GetDefaultLightSpot();
            graphics->SetTexture(TU_LIGHTSHAPE, shapeTexture);
        }
    }
}
Пример #14
0
void Gizmo::SetScreenRect(const IntRect& rect)
{
    displayPos_ = ToImGui(rect.Min());
    displaySize_.x = rect.Width();
    displaySize_.y = rect.Height();
}
Пример #15
0
void Batch::Prepare(View* view, Camera* camera, bool setModelTransform, bool allowDepthWrite) const
{
    if (!vertexShader_ || !pixelShader_)
        return;

    Graphics* graphics = view->GetGraphics();
    Renderer* renderer = view->GetRenderer();
    Node* cameraNode = camera ? camera->GetNode() : 0;
    Light* light = lightQueue_ ? lightQueue_->light_ : 0;
    Texture2D* shadowMap = lightQueue_ ? lightQueue_->shadowMap_ : 0;

    // Set shaders first. The available shader parameters and their register/uniform positions depend on the currently set shaders
    graphics->SetShaders(vertexShader_, pixelShader_);

    // Set pass / material-specific renderstates
    if (pass_ && material_)
    {
        BlendMode blend = pass_->GetBlendMode();
        // Turn additive blending into subtract if the light is negative
        if (light && light->IsNegative())
        {
            if (blend == BLEND_ADD)
                blend = BLEND_SUBTRACT;
            else if (blend == BLEND_ADDALPHA)
                blend = BLEND_SUBTRACTALPHA;
        }
        graphics->SetBlendMode(blend);

        bool isShadowPass = pass_->GetIndex() == Technique::shadowPassIndex;
        CullMode effectiveCullMode = pass_->GetCullMode();
        // Get cull mode from material if pass doesn't override it
        if (effectiveCullMode == MAX_CULLMODES)
            effectiveCullMode = isShadowPass ? material_->GetShadowCullMode() : material_->GetCullMode();

        renderer->SetCullMode(effectiveCullMode, camera);
        if (!isShadowPass)
        {
            const BiasParameters& depthBias = material_->GetDepthBias();
            graphics->SetDepthBias(depthBias.constantBias_, depthBias.slopeScaledBias_);
        }

        // Use the "least filled" fill mode combined from camera & material
        graphics->SetFillMode((FillMode)(Max(camera->GetFillMode(), material_->GetFillMode())));
        graphics->SetDepthTest(pass_->GetDepthTestMode());
        graphics->SetDepthWrite(pass_->GetDepthWrite() && allowDepthWrite);
    }

    // Set global (per-frame) shader parameters
    if (graphics->NeedParameterUpdate(SP_FRAME, (void*)0))
        view->SetGlobalShaderParameters();

    // Set camera & viewport shader parameters
    unsigned cameraHash = (unsigned)(size_t)camera;
    IntRect viewport = graphics->GetViewport();
    IntVector2 viewSize = IntVector2(viewport.Width(), viewport.Height());
    unsigned viewportHash = (unsigned)(viewSize.x_ | (viewSize.y_ << 16));
    if (graphics->NeedParameterUpdate(SP_CAMERA, reinterpret_cast<const void*>(cameraHash + viewportHash)))
    {
        view->SetCameraShaderParameters(camera);
        // During renderpath commands the G-Buffer or viewport texture is assumed to always be viewport-sized
        view->SetGBufferShaderParameters(viewSize, IntRect(0, 0, viewSize.x_, viewSize.y_));
    }

    // Set model or skinning transforms
    if (setModelTransform && graphics->NeedParameterUpdate(SP_OBJECT, worldTransform_))
    {
        if (geometryType_ == GEOM_SKINNED)
        {
            graphics->SetShaderParameter(VSP_SKINMATRICES, reinterpret_cast<const float*>(worldTransform_),
                12 * numWorldTransforms_);
        }
        else
            graphics->SetShaderParameter(VSP_MODEL, *worldTransform_);

        // Set the orientation for billboards, either from the object itself or from the camera
        if (geometryType_ == GEOM_BILLBOARD)
        {
            if (numWorldTransforms_ > 1)
                graphics->SetShaderParameter(VSP_BILLBOARDROT, worldTransform_[1].RotationMatrix());
            else
                graphics->SetShaderParameter(VSP_BILLBOARDROT, cameraNode->GetWorldRotation().RotationMatrix());
        }
    }

    // Set zone-related shader parameters
    BlendMode blend = graphics->GetBlendMode();
    // If the pass is additive, override fog color to black so that shaders do not need a separate additive path
    bool overrideFogColorToBlack = blend == BLEND_ADD || blend == BLEND_ADDALPHA;
    unsigned zoneHash = (unsigned)(size_t)zone_;
    if (overrideFogColorToBlack)
        zoneHash += 0x80000000;
    if (zone_ && graphics->NeedParameterUpdate(SP_ZONE, reinterpret_cast<const void*>(zoneHash)))
    {
        graphics->SetShaderParameter(VSP_AMBIENTSTARTCOLOR, zone_->GetAmbientStartColor());
        graphics->SetShaderParameter(VSP_AMBIENTENDCOLOR,
            zone_->GetAmbientEndColor().ToVector4() - zone_->GetAmbientStartColor().ToVector4());

        const BoundingBox& box = zone_->GetBoundingBox();
        Vector3 boxSize = box.Size();
        Matrix3x4 adjust(Matrix3x4::IDENTITY);
        adjust.SetScale(Vector3(1.0f / boxSize.x_, 1.0f / boxSize.y_, 1.0f / boxSize.z_));
        adjust.SetTranslation(Vector3(0.5f, 0.5f, 0.5f));
        Matrix3x4 zoneTransform = adjust * zone_->GetInverseWorldTransform();
        graphics->SetShaderParameter(VSP_ZONE, zoneTransform);

        graphics->SetShaderParameter(PSP_AMBIENTCOLOR, zone_->GetAmbientColor());
        graphics->SetShaderParameter(PSP_FOGCOLOR, overrideFogColorToBlack ? Color::BLACK : zone_->GetFogColor());

        float farClip = camera->GetFarClip();
        float fogStart = Min(zone_->GetFogStart(), farClip);
        float fogEnd = Min(zone_->GetFogEnd(), farClip);
        if (fogStart >= fogEnd * (1.0f - M_LARGE_EPSILON))
            fogStart = fogEnd * (1.0f - M_LARGE_EPSILON);
        float fogRange = Max(fogEnd - fogStart, M_EPSILON);
        Vector4 fogParams(fogEnd / farClip, farClip / fogRange, 0.0f, 0.0f);

        Node* zoneNode = zone_->GetNode();
        if (zone_->GetHeightFog() && zoneNode)
        {
            Vector3 worldFogHeightVec = zoneNode->GetWorldTransform() * Vector3(0.0f, zone_->GetFogHeight(), 0.0f);
            fogParams.z_ = worldFogHeightVec.y_;
            fogParams.w_ = zone_->GetFogHeightScale() / Max(zoneNode->GetWorldScale().y_, M_EPSILON);
        }

        graphics->SetShaderParameter(PSP_FOGPARAMS, fogParams);
    }

    // Set light-related shader parameters
    if (lightQueue_)
    {
        if (light && graphics->NeedParameterUpdate(SP_LIGHT, lightQueue_))
        {
            Node* lightNode = light->GetNode();
            float atten = 1.0f / Max(light->GetRange(), M_EPSILON);
            Vector3 lightDir(lightNode->GetWorldRotation() * Vector3::BACK);
            Vector4 lightPos(lightNode->GetWorldPosition(), atten);

            graphics->SetShaderParameter(VSP_LIGHTDIR, lightDir);
            graphics->SetShaderParameter(VSP_LIGHTPOS, lightPos);

            if (graphics->HasShaderParameter(VSP_LIGHTMATRICES))
            {
                switch (light->GetLightType())
                {
                case LIGHT_DIRECTIONAL:
                    {
                        Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
                        unsigned numSplits = Min(MAX_CASCADE_SPLITS, lightQueue_->shadowSplits_.Size());

                        for (unsigned i = 0; i < numSplits; ++i)
                            CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer);

                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
                    }
                    break;

                case LIGHT_SPOT:
                    {
                        Matrix4 shadowMatrices[2];

                        CalculateSpotMatrix(shadowMatrices[0], light);
                        bool isShadowed = shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP);
                        if (isShadowed)
                            CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer);

                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
                    }
                    break;

                case LIGHT_POINT:
                    {
                        Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
                        // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
                        // the next parameter
#ifdef ATOMIC_OPENGL
                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 16);
#else
                        graphics->SetShaderParameter(VSP_LIGHTMATRICES, lightVecRot.Data(), 12);
#endif
                    }
                    break;
                }
            }

            float fade = 1.0f;
            float fadeEnd = light->GetDrawDistance();
            float fadeStart = light->GetFadeDistance();

            // Do fade calculation for light if both fade & draw distance defined
            if (light->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
                fade = Min(1.0f - (light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);

            // Negative lights will use subtract blending, so write absolute RGB values to the shader parameter
            graphics->SetShaderParameter(PSP_LIGHTCOLOR, Color(light->GetEffectiveColor().Abs(),
                light->GetEffectiveSpecularIntensity()) * fade);
            graphics->SetShaderParameter(PSP_LIGHTDIR, lightDir);
            graphics->SetShaderParameter(PSP_LIGHTPOS, lightPos);

            if (graphics->HasShaderParameter(PSP_LIGHTMATRICES))
            {
                switch (light->GetLightType())
                {
                case LIGHT_DIRECTIONAL:
                    {
                        Matrix4 shadowMatrices[MAX_CASCADE_SPLITS];
                        unsigned numSplits = Min(MAX_CASCADE_SPLITS, lightQueue_->shadowSplits_.Size());

                        for (unsigned i = 0; i < numSplits; ++i)
                            CalculateShadowMatrix(shadowMatrices[i], lightQueue_, i, renderer);

                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), 16 * numSplits);
                    }
                    break;

                case LIGHT_SPOT:
                    {
                        Matrix4 shadowMatrices[2];

                        CalculateSpotMatrix(shadowMatrices[0], light);
                        bool isShadowed = lightQueue_->shadowMap_ != 0;
                        if (isShadowed)
                            CalculateShadowMatrix(shadowMatrices[1], lightQueue_, 0, renderer);

                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, shadowMatrices[0].Data(), isShadowed ? 32 : 16);
                    }
                    break;

                case LIGHT_POINT:
                    {
                        Matrix4 lightVecRot(lightNode->GetWorldRotation().RotationMatrix());
                        // HLSL compiler will pack the parameters as if the matrix is only 3x4, so must be careful to not overwrite
                        // the next parameter
#ifdef ATOMIC_OPENGL
                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 16);
#else
                        graphics->SetShaderParameter(PSP_LIGHTMATRICES, lightVecRot.Data(), 12);
#endif
                    }
                    break;
                }
            }

            // Set shadow mapping shader parameters
            if (shadowMap)
            {
                {
                    // Calculate point light shadow sampling offsets (unrolled cube map)
                    unsigned faceWidth = (unsigned)(shadowMap->GetWidth() / 2);
                    unsigned faceHeight = (unsigned)(shadowMap->GetHeight() / 3);
                    float width = (float)shadowMap->GetWidth();
                    float height = (float)shadowMap->GetHeight();
#ifdef ATOMIC_OPENGL
                    float mulX = (float)(faceWidth - 3) / width;
                    float mulY = (float)(faceHeight - 3) / height;
                    float addX = 1.5f / width;
                    float addY = 1.5f / height;
#else
                    float mulX = (float)(faceWidth - 4) / width;
                    float mulY = (float)(faceHeight - 4) / height;
                    float addX = 2.5f / width;
                    float addY = 2.5f / height;
#endif
                    // If using 4 shadow samples, offset the position diagonally by half pixel
                    if (renderer->GetShadowQuality() == SHADOWQUALITY_PCF_16BIT || renderer->GetShadowQuality() == SHADOWQUALITY_PCF_24BIT)
                    {
                        addX -= 0.5f / width;
                        addY -= 0.5f / height;
                    }
                    graphics->SetShaderParameter(PSP_SHADOWCUBEADJUST, Vector4(mulX, mulY, addX, addY));
                }

                {
                    // Calculate shadow camera depth parameters for point light shadows and shadow fade parameters for
                    //  directional light shadows, stored in the same uniform
                    Camera* shadowCamera = lightQueue_->shadowSplits_[0].shadowCamera_;
                    float nearClip = shadowCamera->GetNearClip();
                    float farClip = shadowCamera->GetFarClip();
                    float q = farClip / (farClip - nearClip);
                    float r = -q * nearClip;

                    const CascadeParameters& parameters = light->GetShadowCascade();
                    float viewFarClip = camera->GetFarClip();
                    float shadowRange = parameters.GetShadowRange();
                    float fadeStart = parameters.fadeStart_ * shadowRange / viewFarClip;
                    float fadeEnd = shadowRange / viewFarClip;
                    float fadeRange = fadeEnd - fadeStart;

                    graphics->SetShaderParameter(PSP_SHADOWDEPTHFADE, Vector4(q, r, fadeStart, 1.0f / fadeRange));
                }

                {
                    float intensity = light->GetShadowIntensity();
                    float fadeStart = light->GetShadowFadeDistance();
                    float fadeEnd = light->GetShadowDistance();
                    if (fadeStart > 0.0f && fadeEnd > 0.0f && fadeEnd > fadeStart)
                        intensity =
                            Lerp(intensity, 1.0f, Clamp((light->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 0.0f, 1.0f));
                    float pcfValues = (1.0f - intensity);
                    float samples = 1.0f;
                    if (renderer->GetShadowQuality() == SHADOWQUALITY_PCF_16BIT || renderer->GetShadowQuality() == SHADOWQUALITY_PCF_24BIT)
                        samples = 4.0f;
                    graphics->SetShaderParameter(PSP_SHADOWINTENSITY, Vector4(pcfValues / samples, intensity, 0.0f, 0.0f));
                }

                float sizeX = 1.0f / (float)shadowMap->GetWidth();
                float sizeY = 1.0f / (float)shadowMap->GetHeight();
                graphics->SetShaderParameter(PSP_SHADOWMAPINVSIZE, Vector2(sizeX, sizeY));

                Vector4 lightSplits(M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE, M_LARGE_VALUE);
                if (lightQueue_->shadowSplits_.Size() > 1)
                    lightSplits.x_ = lightQueue_->shadowSplits_[0].farSplit_ / camera->GetFarClip();
                if (lightQueue_->shadowSplits_.Size() > 2)
                    lightSplits.y_ = lightQueue_->shadowSplits_[1].farSplit_ / camera->GetFarClip();
                if (lightQueue_->shadowSplits_.Size() > 3)
                    lightSplits.z_ = lightQueue_->shadowSplits_[2].farSplit_ / camera->GetFarClip();

                graphics->SetShaderParameter(PSP_SHADOWSPLITS, lightSplits);

                if (graphics->HasShaderParameter(PSP_VSMSHADOWPARAMS))
                    graphics->SetShaderParameter(PSP_VSMSHADOWPARAMS, renderer->GetVSMShadowParameters());

                if (light->GetShadowBias().normalOffset_ > 0.0f)
                {
                    Vector4 normalOffsetScale(Vector4::ZERO);

                    // Scale normal offset strength with the width of the shadow camera view
                    if (light->GetLightType() != LIGHT_DIRECTIONAL)
                    {
                        Camera* shadowCamera = lightQueue_->shadowSplits_[0].shadowCamera_;
                        normalOffsetScale.x_ = 2.0f * tanf(shadowCamera->GetFov() * M_DEGTORAD * 0.5f) * shadowCamera->GetFarClip();
                    }
                    else
                    {
                        normalOffsetScale.x_ = lightQueue_->shadowSplits_[0].shadowCamera_->GetOrthoSize();
                        if (lightQueue_->shadowSplits_.Size() > 1)
                            normalOffsetScale.y_ = lightQueue_->shadowSplits_[1].shadowCamera_->GetOrthoSize();
                        if (lightQueue_->shadowSplits_.Size() > 2)
                            normalOffsetScale.z_ = lightQueue_->shadowSplits_[2].shadowCamera_->GetOrthoSize();
                        if (lightQueue_->shadowSplits_.Size() > 3)
                            normalOffsetScale.w_ = lightQueue_->shadowSplits_[3].shadowCamera_->GetOrthoSize();
                    }

                    normalOffsetScale *= light->GetShadowBias().normalOffset_;
#ifdef GL_ES_VERSION_2_0
                    normalOffsetScale *= renderer->GetMobileNormalOffsetMul();
#endif
                    graphics->SetShaderParameter(VSP_NORMALOFFSETSCALE, normalOffsetScale);
                    graphics->SetShaderParameter(PSP_NORMALOFFSETSCALE, normalOffsetScale);
                }
            }
        }
        else if (lightQueue_->vertexLights_.Size() && graphics->HasShaderParameter(VSP_VERTEXLIGHTS) &&
                 graphics->NeedParameterUpdate(SP_LIGHT, lightQueue_))
        {
            Vector4 vertexLights[MAX_VERTEX_LIGHTS * 3];
            const PODVector<Light*>& lights = lightQueue_->vertexLights_;

            for (unsigned i = 0; i < lights.Size(); ++i)
            {
                Light* vertexLight = lights[i];
                Node* vertexLightNode = vertexLight->GetNode();
                LightType type = vertexLight->GetLightType();

                // Attenuation
                float invRange, cutoff, invCutoff;
                if (type == LIGHT_DIRECTIONAL)
                    invRange = 0.0f;
                else
                    invRange = 1.0f / Max(vertexLight->GetRange(), M_EPSILON);
                if (type == LIGHT_SPOT)
                {
                    cutoff = Cos(vertexLight->GetFov() * 0.5f);
                    invCutoff = 1.0f / (1.0f - cutoff);
                }
                else
                {
                    cutoff = -1.0f;
                    invCutoff = 1.0f;
                }

                // Color
                float fade = 1.0f;
                float fadeEnd = vertexLight->GetDrawDistance();
                float fadeStart = vertexLight->GetFadeDistance();

                // Do fade calculation for light if both fade & draw distance defined
                if (vertexLight->GetLightType() != LIGHT_DIRECTIONAL && fadeEnd > 0.0f && fadeStart > 0.0f && fadeStart < fadeEnd)
                    fade = Min(1.0f - (vertexLight->GetDistance() - fadeStart) / (fadeEnd - fadeStart), 1.0f);

                Color color = vertexLight->GetEffectiveColor() * fade;
                vertexLights[i * 3] = Vector4(color.r_, color.g_, color.b_, invRange);

                // Direction
                vertexLights[i * 3 + 1] = Vector4(-(vertexLightNode->GetWorldDirection()), cutoff);

                // Position
                vertexLights[i * 3 + 2] = Vector4(vertexLightNode->GetWorldPosition(), invCutoff);
            }

            graphics->SetShaderParameter(VSP_VERTEXLIGHTS, vertexLights[0].Data(), lights.Size() * 3 * 4);
        }
    }

    // Set zone texture if necessary
#ifndef GL_ES_VERSION_2_0
    if (zone_ && graphics->HasTextureUnit(TU_ZONE))
        graphics->SetTexture(TU_ZONE, zone_->GetZoneTexture());
#else
    // On OpenGL ES set the zone texture to the environment unit instead
    if (zone_ && zone_->GetZoneTexture() && graphics->HasTextureUnit(TU_ENVIRONMENT))
        graphics->SetTexture(TU_ENVIRONMENT, zone_->GetZoneTexture());
#endif

    // Set material-specific shader parameters and textures
    if (material_)
    {
        if (graphics->NeedParameterUpdate(SP_MATERIAL, reinterpret_cast<const void*>(material_->GetShaderParameterHash())))
        {
            const HashMap<StringHash, MaterialShaderParameter>& parameters = material_->GetShaderParameters();
            for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator i = parameters.Begin(); i != parameters.End(); ++i)
                graphics->SetShaderParameter(i->first_, i->second_.value_);
        }

        const HashMap<TextureUnit, SharedPtr<Texture> >& textures = material_->GetTextures();
        for (HashMap<TextureUnit, SharedPtr<Texture> >::ConstIterator i = textures.Begin(); i != textures.End(); ++i)
        {
            if (graphics->HasTextureUnit(i->first_))
                graphics->SetTexture(i->first_, i->second_.Get());
        }
    }

    // Set light-related textures
    if (light)
    {
        if (shadowMap && graphics->HasTextureUnit(TU_SHADOWMAP))
            graphics->SetTexture(TU_SHADOWMAP, shadowMap);
        if (graphics->HasTextureUnit(TU_LIGHTRAMP))
        {
            Texture* rampTexture = light->GetRampTexture();
            if (!rampTexture)
                rampTexture = renderer->GetDefaultLightRamp();
            graphics->SetTexture(TU_LIGHTRAMP, rampTexture);
        }
        if (graphics->HasTextureUnit(TU_LIGHTSHAPE))
        {
            Texture* shapeTexture = light->GetShapeTexture();
            if (!shapeTexture && light->GetLightType() == LIGHT_SPOT)
                shapeTexture = renderer->GetDefaultLightSpot();
            graphics->SetTexture(TU_LIGHTSHAPE, shapeTexture);
        }
    }
}
Пример #16
0
void onMouse(int event, int x, int y, int, void*)
{
	if (selectObject)
	{
		selectionRegion.SetXMin(MIN(x, originMouse.x));
		selectionRegion.SetYMin(MIN(y, originMouse.y));
		selectionRegion.SetWidth(std::abs(x - originMouse.x));
		selectionRegion.SetHeight(std::abs(y - originMouse.y));

	}
	switch (event)
	{
	case CV_EVENT_LBUTTONDOWN:
		printf("buttondown:    x:%d,y:%d\n",x,y);
		originMouse = Point(x, y);
		selectionRegion = IntRect(x, y, 0, 0);
		selectObject = true;
		break;
	case CV_EVENT_LBUTTONUP:
		selectObject = false;
	    newregion = true;
		trackObject = -1;
		printf("buttonup:    x:%d,y:%d,width:%d,height:%d\n", selectionRegion.XMin(), selectionRegion.YMin(), selectionRegion.Height(), selectionRegion.Width());
		break;
	}
}
Пример #17
0
SceneEditor3D ::SceneEditor3D(Context* context, const String &fullpath, UITabContainer *container) :
    ResourceEditor(context, fullpath, container)
{
    ResourceCache* cache = GetSubsystem<ResourceCache>();

    scene_ = new Scene(context_);
    SharedPtr<File> xmlFile = cache->GetFile(fullpath);

    if (GetExtension(fullpath) == ".scene")
        scene_->LoadXML(*xmlFile);
    else
        scene_->Load(*xmlFile);

    scene_->SetUpdateEnabled(false);

    sceneView_ = new SceneView3D(context_, this);

    // EARLY ACCESS
    if (fullpath.Find(String("ToonTown")) != String::NPOS)
    {
          sceneView_->GetCameraNode()->SetWorldPosition(Vector3(-119.073f, 76.1121f, 16.47763f));
          Quaternion q(0.55f, 0.14f,  0.8f, -0.2f);
          sceneView_->SetYaw(q.YawAngle());
          sceneView_->SetPitch(q.PitchAngle());
          sceneView_->GetCameraNode()->SetWorldRotation(q);
    }
    else
    {
        Node* playerSpawn = scene_->GetChild("PlayerInfoStart", true);
        if (playerSpawn)
        {
            sceneView_->GetCameraNode()->SetPosition(playerSpawn->GetPosition());
            sceneView_->SetYaw(playerSpawn->GetRotation().EulerAngles().y_);
        }

    }

    sceneView_->SetGravity(UI_GRAVITY_ALL);

    rootContentWidget_->AddChild(sceneView_);

    gizmo3D_ = new Gizmo3D(context_);
    gizmo3D_->SetView(sceneView_);
    gizmo3D_->Show();

    SubscribeToEvent(E_UPDATE, HANDLER(SceneEditor3D, HandleUpdate));
    SubscribeToEvent(E_EDITORACTIVENODECHANGE, HANDLER(SceneEditor3D, HandleEditorActiveNodeChange));

    SubscribeToEvent(E_GIZMOEDITMODECHANGED, HANDLER(SceneEditor3D, HandleGizmoEditModeChanged));

    // FIXME: Set the size at the end of setup, so all children are updated accordingly
    // future size changes will be handled automatically
    IntRect rect = container_->GetContentRoot()->GetRect();
    rootContentWidget_->SetSize(rect.Width(), rect.Height());

    SubscribeToEvent(E_EDITORPLAYSTARTED, HANDLER(SceneEditor3D, HandlePlayStarted));
    SubscribeToEvent(E_EDITORPLAYSTOPPED, HANDLER(SceneEditor3D, HandlePlayStopped));

    SubscribeToEvent(scene_, E_NODEREMOVED, HANDLER(SceneEditor3D, HandleNodeRemoved));

}
Пример #18
0
    /// Convert screen coordinates to element coordinates.
    IntVector2 ScreenToElement(const IntVector2& screenPos) override
    {
        IntVector2 result(-1, -1);

        if (node_.Expired())
            return result;

        Scene* scene = node_->GetScene();
        auto* model = node_->GetComponent<StaticModel>();
        if (scene == nullptr || model == nullptr)
            return result;

        auto* renderer = GetSubsystem<Renderer>();
        if (renderer == nullptr)
            return result;

        // \todo Always uses the first viewport, in case there are multiple
        auto* octree = scene->GetComponent<Octree>();
        if (viewport_ == nullptr)
            viewport_ = renderer->GetViewportForScene(scene, 0);

        if (viewport_.Expired() || octree == nullptr)
            return result;

        if (viewport_->GetScene() != scene)
        {
            URHO3D_LOGERROR("UIComponent and Viewport set to component's root element belong to different scenes.");
            return result;
        }

        Camera* camera = viewport_->GetCamera();

        if (camera == nullptr)
            return result;

        IntRect rect = viewport_->GetRect();
        if (rect == IntRect::ZERO)
        {
            auto* graphics = GetSubsystem<Graphics>();
            rect.right_ = graphics->GetWidth();
            rect.bottom_ = graphics->GetHeight();
        }

        Ray ray(camera->GetScreenRay((float)screenPos.x_ / rect.Width(), (float)screenPos.y_ / rect.Height()));
        PODVector<RayQueryResult> queryResultVector;
        RayOctreeQuery query(queryResultVector, ray, RAY_TRIANGLE_UV, M_INFINITY, DRAWABLE_GEOMETRY, DEFAULT_VIEWMASK);

        octree->Raycast(query);

        if (queryResultVector.Empty())
            return result;

        for (unsigned i = 0; i < queryResultVector.Size(); i++)
        {
            RayQueryResult& queryResult = queryResultVector[i];
            if (queryResult.drawable_ != model)
            {
                // ignore billboard sets by default
                if (queryResult.drawable_->GetTypeInfo()->IsTypeOf(BillboardSet::GetTypeStatic()))
                    continue;
                return result;
            }

            Vector2& uv = queryResult.textureUV_;
            result = IntVector2(static_cast<int>(uv.x_ * GetWidth()),
                static_cast<int>(uv.y_ * GetHeight()));
            return result;
        }
        return result;
    }