void CalculateSpotMatrix(Matrix4& dest, Light* light, const Vector3& translation) { Node* lightNode = light->GetNode(); Matrix3x4 posAdjust(translation, Quaternion::IDENTITY, 1.0f); Matrix3x4 spotView = Matrix3x4(lightNode->GetWorldPosition(), lightNode->GetWorldRotation(), 1.0f).Inverse(); Matrix4 spotProj(Matrix4::ZERO); Matrix4 texAdjust(Matrix4::IDENTITY); // Make the projected light slightly smaller than the shadow map to prevent light spill float h = 1.005f / tanf(light->GetFov() * M_DEGTORAD * 0.5f); float w = h / light->GetAspectRatio(); spotProj.m00_ = w; spotProj.m11_ = h; spotProj.m22_ = 1.0f / Max(light->GetRange(), M_EPSILON); spotProj.m32_ = 1.0f; #ifdef URHO3D_OPENGL texAdjust.SetTranslation(Vector3(0.5f, 0.5f, 0.5f)); texAdjust.SetScale(Vector3(0.5f, -0.5f, 0.5f)); #else texAdjust.SetTranslation(Vector3(0.5f, 0.5f, 0.0f)); texAdjust.SetScale(Vector3(0.5f, -0.5f, 1.0f)); #endif dest = texAdjust * spotProj * spotView * posAdjust; }
void DiSprite::UpdateGeometry(DiRenderTarget* rt) { if (mQuads.empty()) { mPrimitiveCount = 0; return; } if (!rt) return; ReleaseSourceData(); auto vb = Driver->CreateVertexBuffer(); if (!vb) return; mSourceData.push_back(vb); mVerticesNum = 6 * mQuads.size(); mPrimitiveCount = 2 * mQuads.size(); uint32 vertSize = (3 + 2) * sizeof(float) + sizeof(ARGB); mSourceData[0]->Create(mVerticesNum*vertSize); uint8* lockedData = DI_NEW uint8[mVerticesNum*vertSize]; uint32 w = (uint32)(rt->GetWidth() * rt->GetViewport().mWidth); uint32 h = (uint32)(rt->GetHeight() * rt->GetViewport().mHeight); DiVec2 invScreenSize; invScreenSize = DiVec2(1.0f / (float)w, 1.0f / (float)h); DiVec2 posAdjust(1, -1); float* dest = (float*)lockedData; if (!mMaterial || mMaterial->HasTexture()) { for (auto it = mQuads.begin(); it != mQuads.end(); ++it) { DiQuadElement quad = *it; DiVec2 topLeft, bottomRight, topLeftUv, bottomRightUv; quad.top *= -1; quad.bottom *= -1; if (!quad.absCoord) { quad.left *= (float)w; quad.right *= (float)w; quad.top *= (float)h; quad.bottom *= (float)h; } topLeft = (DiVec2((float)quad.left, (float)quad.top)/*+DiVec2(0.5f,0.5f)*/) * invScreenSize*2; bottomRight = (DiVec2((float)quad.right, (float)quad.bottom)/*+DiVec2(0.5f,0.5f)*/) * invScreenSize*2; topLeft -= posAdjust; bottomRight -= posAdjust; topLeftUv = DiVec2((float)quad.leftUv, (float)quad.topUv); bottomRightUv = DiVec2((float)quad.rightUv, (float)quad.bottomUv); *dest++ = topLeft.x; *dest++ = topLeft.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.topLeftColor; dest++; *dest++ = topLeftUv.x; *dest++ = topLeftUv.y; *dest++ = topLeft.x; *dest++ = bottomRight.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.bottomLeftColor; dest++; *dest++ = topLeftUv.x; *dest++ = bottomRightUv.y; *dest++ = bottomRight.x; *dest++ = topLeft.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.topRightColor; dest++; *dest++ = bottomRightUv.x; *dest++ = topLeftUv.y; *dest++ = bottomRight.x; *dest++ = topLeft.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.topRightColor; dest++; *dest++ = bottomRightUv.x; *dest++ = topLeftUv.y; *dest++ = topLeft.x; *dest++ = bottomRight.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.bottomLeftColor; dest++; *dest++ = topLeftUv.x; *dest++ = bottomRightUv.y; *dest++ = bottomRight.x; *dest++ = bottomRight.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.bottomRightColor; dest++; *dest++ = bottomRightUv.x; *dest++ = bottomRightUv.y; } } else { for (auto it = mQuads.begin(); it != mQuads.end(); ++it) { DiQuadElement quad = *it; quad.top *= -1; quad.bottom *= -1; if (!quad.absCoord) { quad.left *= (float)w; quad.right *= (float)w; quad.top *= (float)h; quad.bottom *= (float)h; } DiVec2 topLeft, bottomRight, topLeftUV, bottomRightUV; topLeft = (DiVec2((float)quad.left, (float)quad.top)) * invScreenSize*2; bottomRight = (DiVec2((float)quad.right, (float)quad.bottom)) * invScreenSize*2; topLeft -= posAdjust; bottomRight -= posAdjust; *dest++ = topLeft.x; *dest++ = topLeft.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.topLeftColor; dest++; dest += 2; *dest++ = topLeft.x; *dest++ = bottomRight.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.bottomLeftColor; dest++; dest += 2; *dest++ = bottomRight.x; *dest++ = topLeft.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.topRightColor; dest++; dest += 2; *dest++ = bottomRight.x; *dest++ = topLeft.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.topRightColor; dest++; dest += 2; *dest++ = topLeft.x; *dest++ = bottomRight.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.bottomLeftColor; dest++; dest += 2; *dest++ = bottomRight.x; *dest++ = bottomRight.y; *dest++ = 0.0f; *((ARGB*)dest) = quad.bottomRightColor; dest++; dest += 2; } } mSourceData[0]->WriteData(0, mVerticesNum*vertSize, lockedData); DI_DELETE[] lockedData; mSourceData[0]->SetStride(vertSize); }