зеркало из https://github.com/mozilla/pjs.git
Bug 717393 - Part 4: Add code for drawing subpixel AA to transparent surfaces. r=jrmuizel
This commit is contained in:
Родитель
7c0d03d066
Коммит
be70d283dc
10
gfx/2d/2D.h
10
gfx/2d/2D.h
|
@ -792,11 +792,21 @@ public:
|
|||
const IntRect &GetOpaqueRect() const {
|
||||
return mOpaqueRect;
|
||||
}
|
||||
|
||||
void SetPermitSubpixelAA(bool aPermitSubpixelAA) {
|
||||
mPermitSubpixelAA = aPermitSubpixelAA;
|
||||
}
|
||||
|
||||
bool GetPermitSubpixelAA() {
|
||||
return mPermitSubpixelAA;
|
||||
}
|
||||
|
||||
protected:
|
||||
UserData mUserData;
|
||||
Matrix mTransform;
|
||||
IntRect mOpaqueRect;
|
||||
bool mTransformDirty : 1;
|
||||
bool mPermitSubpixelAA : 1;
|
||||
|
||||
SurfaceFormat mFormat;
|
||||
};
|
||||
|
|
|
@ -47,6 +47,8 @@
|
|||
#include "Tools.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include <dwrite.h>
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
@ -67,6 +69,12 @@ typedef HRESULT (WINAPI*D3D10CreateEffectFromMemoryFunc)(
|
|||
ID3D10Effect **ppEffect
|
||||
);
|
||||
|
||||
typedef HRESULT (WINAPI*DWriteCreateFactoryFunc)(
|
||||
DWRITE_FACTORY_TYPE factoryType,
|
||||
REFIID iid,
|
||||
IUnknown **factory
|
||||
);
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace mozilla {
|
||||
|
@ -78,6 +86,7 @@ struct Vertex {
|
|||
};
|
||||
|
||||
ID2D1Factory *DrawTargetD2D::mFactory;
|
||||
IDWriteFactory *DrawTargetD2D::mDWriteFactory;
|
||||
|
||||
// Helper class to restore surface contents that was clipped out but may have
|
||||
// been altered by a drawing call.
|
||||
|
@ -871,10 +880,6 @@ DrawTargetD2D::FillGlyphs(ScaledFont *aFont,
|
|||
|
||||
ScaledFontDWrite *font = static_cast<ScaledFontDWrite*>(aFont);
|
||||
|
||||
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
|
||||
|
||||
PrepareForDrawing(rt);
|
||||
|
||||
IDWriteRenderingParams *params = NULL;
|
||||
if (aRenderOptions) {
|
||||
if (aRenderOptions->GetType() != FONT_DWRITE) {
|
||||
|
@ -886,6 +891,19 @@ DrawTargetD2D::FillGlyphs(ScaledFont *aFont,
|
|||
}
|
||||
}
|
||||
|
||||
if (mFormat == FORMAT_B8G8R8A8 && mPermitSubpixelAA &&
|
||||
aOptions.mCompositionOp == OP_OVER && aPattern.GetType() == PATTERN_COLOR) {
|
||||
if (FillGlyphsManual(font, aBuffer,
|
||||
static_cast<const ColorPattern*>(&aPattern)->mColor,
|
||||
params, aOptions)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
ID2D1RenderTarget *rt = GetRTForOperation(aOptions.mCompositionOp, aPattern);
|
||||
|
||||
PrepareForDrawing(rt);
|
||||
|
||||
rt->SetTextRenderingParams(params);
|
||||
|
||||
RefPtr<ID2D1Brush> brush = CreateBrushForPattern(aPattern, aOptions.mAlpha);
|
||||
|
@ -1702,7 +1720,7 @@ DrawTargetD2D::PopClipsFromRT(ID2D1RenderTarget *aRT)
|
|||
void
|
||||
DrawTargetD2D::EnsureClipMaskTexture()
|
||||
{
|
||||
if (mCurrentClipMaskTexture) {
|
||||
if (mCurrentClipMaskTexture || mPushedClips.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1737,6 +1755,172 @@ DrawTargetD2D::EnsureClipMaskTexture()
|
|||
rt->EndDraw();
|
||||
}
|
||||
|
||||
bool
|
||||
DrawTargetD2D::FillGlyphsManual(ScaledFontDWrite *aFont,
|
||||
const GlyphBuffer &aBuffer,
|
||||
const Color &aColor,
|
||||
IDWriteRenderingParams *aParams,
|
||||
const DrawOptions &aOptions)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
RefPtr<IDWriteRenderingParams> params;
|
||||
|
||||
if (aParams) {
|
||||
params = aParams;
|
||||
} else {
|
||||
mRT->GetTextRenderingParams(byRef(params));
|
||||
}
|
||||
|
||||
DWRITE_RENDERING_MODE renderMode = DWRITE_RENDERING_MODE_DEFAULT;
|
||||
if (params) {
|
||||
hr = aFont->mFontFace->GetRecommendedRenderingMode(
|
||||
(FLOAT)aFont->mSize,
|
||||
1.0f,
|
||||
DWRITE_MEASURING_MODE_NATURAL,
|
||||
params,
|
||||
&renderMode);
|
||||
if (FAILED(hr)) {
|
||||
// this probably never happens, but let's play it safe
|
||||
renderMode = DWRITE_RENDERING_MODE_DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
// Deal with rendering modes CreateGlyphRunAnalysis doesn't accept.
|
||||
switch (renderMode) {
|
||||
case DWRITE_RENDERING_MODE_ALIASED:
|
||||
// ClearType texture creation will fail in this mode, so bail out
|
||||
return false;
|
||||
case DWRITE_RENDERING_MODE_DEFAULT:
|
||||
// As per DWRITE_RENDERING_MODE documentation, pick Natural for font
|
||||
// sizes under 16 ppem
|
||||
if (aFont->mSize < 16.0f) {
|
||||
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL;
|
||||
} else {
|
||||
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
||||
}
|
||||
break;
|
||||
case DWRITE_RENDERING_MODE_OUTLINE:
|
||||
renderMode = DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
DWRITE_MEASURING_MODE measureMode =
|
||||
renderMode <= DWRITE_RENDERING_MODE_CLEARTYPE_GDI_CLASSIC ? DWRITE_MEASURING_MODE_GDI_CLASSIC :
|
||||
renderMode == DWRITE_RENDERING_MODE_CLEARTYPE_GDI_NATURAL ? DWRITE_MEASURING_MODE_GDI_NATURAL :
|
||||
DWRITE_MEASURING_MODE_NATURAL;
|
||||
|
||||
DWRITE_MATRIX mat = DWriteMatrixFromMatrix(mTransform);
|
||||
|
||||
AutoDWriteGlyphRun autoRun;
|
||||
DWriteGlyphRunFromGlyphs(aBuffer, aFont, &autoRun);
|
||||
|
||||
RefPtr<IDWriteGlyphRunAnalysis> analysis;
|
||||
hr = GetDWriteFactory()->CreateGlyphRunAnalysis(&autoRun, 1.0f, &mat,
|
||||
renderMode, measureMode, 0, 0, byRef(analysis));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RECT bounds;
|
||||
hr = analysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds);
|
||||
IntRect rectBounds(bounds.left, bounds.top, bounds.right - bounds.left, bounds.bottom - bounds.top);
|
||||
IntRect surfBounds(IntPoint(0, 0), mSize);
|
||||
|
||||
rectBounds.IntersectRect(rectBounds, surfBounds);
|
||||
|
||||
if (rectBounds.IsEmpty()) {
|
||||
// Nothing to do.
|
||||
return true;
|
||||
}
|
||||
|
||||
RefPtr<ID3D10Texture2D> tex = CreateTextureForAnalysis(analysis, rectBounds);
|
||||
|
||||
if (!tex) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RefPtr<ID3D10ShaderResourceView> srView;
|
||||
hr = mDevice->CreateShaderResourceView(tex, NULL, byRef(srView));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MarkChanged();
|
||||
|
||||
// Prepare our background texture for drawing.
|
||||
PopAllClips();
|
||||
mRT->Flush();
|
||||
|
||||
SetupStateForRendering();
|
||||
|
||||
ID3D10EffectTechnique *technique = mPrivateData->mEffect->GetTechniqueByName("SampleTextTexture");
|
||||
|
||||
mPrivateData->mEffect->GetVariableByName("QuadDesc")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(-1.0f + ((Float(rectBounds.x) / mSize.width) * 2.0f),
|
||||
1.0f - (Float(rectBounds.y) / mSize.height * 2.0f),
|
||||
(Float(rectBounds.width) / mSize.width) * 2.0f,
|
||||
(-Float(rectBounds.height) / mSize.height) * 2.0f));
|
||||
mPrivateData->mEffect->GetVariableByName("TexCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(0, 0, 1.0f, 1.0f));
|
||||
FLOAT color[4] = { aColor.r, aColor.g, aColor.b, aColor.a };
|
||||
mPrivateData->mEffect->GetVariableByName("TextColor")->AsVector()->
|
||||
SetFloatVector(color);
|
||||
|
||||
mPrivateData->mEffect->GetVariableByName("tex")->AsShaderResource()->SetResource(srView);
|
||||
|
||||
bool isMasking = false;
|
||||
|
||||
if (!mPushedClips.empty()) {
|
||||
RefPtr<ID2D1Geometry> geom = GetClippedGeometry();
|
||||
|
||||
RefPtr<ID2D1RectangleGeometry> rectGeom;
|
||||
factory()->CreateRectangleGeometry(D2D1::RectF(rectBounds.x, rectBounds.y,
|
||||
rectBounds.width + rectBounds.x,
|
||||
rectBounds.height + rectBounds.y),
|
||||
byRef(rectGeom));
|
||||
|
||||
D2D1_GEOMETRY_RELATION relation;
|
||||
if (FAILED(geom->CompareWithGeometry(rectGeom, D2D1::IdentityMatrix(), &relation)) ||
|
||||
relation != D2D1_GEOMETRY_RELATION_CONTAINS) {
|
||||
isMasking = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMasking) {
|
||||
EnsureClipMaskTexture();
|
||||
|
||||
RefPtr<ID3D10ShaderResourceView> srViewMask;
|
||||
hr = mDevice->CreateShaderResourceView(mCurrentClipMaskTexture, NULL, byRef(srViewMask));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mPrivateData->mEffect->GetVariableByName("mask")->AsShaderResource()->SetResource(srViewMask);
|
||||
|
||||
mPrivateData->mEffect->GetVariableByName("MaskTexCoords")->AsVector()->
|
||||
SetFloatVector(ShaderConstantRectD3D10(Float(rectBounds.x) / mSize.width, Float(rectBounds.y) / mSize.height,
|
||||
Float(rectBounds.width) / mSize.width, Float(rectBounds.height) / mSize.height));
|
||||
|
||||
technique->GetPassByIndex(1)->Apply(0);
|
||||
} else {
|
||||
technique->GetPassByIndex(0)->Apply(0);
|
||||
}
|
||||
|
||||
RefPtr<ID3D10RenderTargetView> rtView;
|
||||
ID3D10RenderTargetView *rtViews;
|
||||
mDevice->CreateRenderTargetView(mTexture, NULL, byRef(rtView));
|
||||
|
||||
rtViews = rtView;
|
||||
mDevice->OMSetRenderTargets(1, &rtViews, NULL);
|
||||
|
||||
mDevice->Draw(4, 0);
|
||||
}
|
||||
|
||||
TemporaryRef<ID2D1Brush>
|
||||
DrawTargetD2D::CreateBrushForPattern(const Pattern &aPattern, Float aAlpha)
|
||||
|
@ -1999,6 +2183,70 @@ DrawTargetD2D::CreateGradientTexture(const GradientStopsD2D *aStops)
|
|||
return tex;
|
||||
}
|
||||
|
||||
TemporaryRef<ID3D10Texture2D>
|
||||
DrawTargetD2D::CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
uint32_t bufferSize = aBounds.width * aBounds.height * 3;
|
||||
|
||||
RECT bounds;
|
||||
bounds.left = aBounds.x;
|
||||
bounds.top = aBounds.y;
|
||||
bounds.right = aBounds.x + aBounds.width;
|
||||
bounds.bottom = aBounds.y + aBounds.height;
|
||||
|
||||
// Add one byte so we can safely read a 32-bit int when copying the last
|
||||
// 3 bytes.
|
||||
BYTE *texture = new BYTE[bufferSize + 1];
|
||||
hr = aAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, &bounds, texture, bufferSize);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
delete [] texture;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int alignedBufferSize = aBounds.width * aBounds.height * 4;
|
||||
|
||||
// Create a one-off immutable texture from system memory.
|
||||
BYTE *alignedTextureData = new BYTE[alignedBufferSize];
|
||||
for (int y = 0; y < aBounds.height; y++) {
|
||||
for (int x = 0; x < aBounds.width; x++) {
|
||||
// Copy 3 Bpp source to 4 Bpp destination memory used for
|
||||
// texture creation. D3D10 has no 3 Bpp texture format we can
|
||||
// use.
|
||||
//
|
||||
// Since we don't care what ends up in the alpha pixel of the
|
||||
// destination, therefor we can simply copy a normal 32 bit
|
||||
// integer each time, filling the alpha pixel of the destination
|
||||
// with the first subpixel of the next pixel from the source.
|
||||
*((int*)(alignedTextureData + (y * aBounds.width + x) * 4)) =
|
||||
*((int*)(texture + (y * aBounds.width + x) * 3));
|
||||
}
|
||||
}
|
||||
|
||||
D3D10_SUBRESOURCE_DATA data;
|
||||
|
||||
CD3D10_TEXTURE2D_DESC desc(DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
aBounds.width, aBounds.height,
|
||||
1, 1);
|
||||
desc.Usage = D3D10_USAGE_IMMUTABLE;
|
||||
|
||||
data.SysMemPitch = aBounds.width * 4;
|
||||
data.pSysMem = alignedTextureData;
|
||||
|
||||
RefPtr<ID3D10Texture2D> tex;
|
||||
hr = mDevice->CreateTexture2D(&desc, &data, byRef(tex));
|
||||
|
||||
delete [] alignedTextureData;
|
||||
delete [] texture;
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return tex;
|
||||
}
|
||||
TemporaryRef<ID2D1Bitmap>
|
||||
DrawTargetD2D::CreatePartialBitmapForSurface(SourceSurfaceD2D *aSurface, Matrix &aMatrix)
|
||||
{
|
||||
|
@ -2173,6 +2421,28 @@ DrawTargetD2D::SetupEffectForRadialGradient(const RadialGradientPattern *aPatter
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
DrawTargetD2D::SetupStateForRendering()
|
||||
{
|
||||
UINT stride = sizeof(Vertex);
|
||||
UINT offset = 0;
|
||||
ID3D10Buffer *buff = mPrivateData->mVB;
|
||||
|
||||
mDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
|
||||
mDevice->IASetVertexBuffers(0, 1, &buff, &stride, &offset);
|
||||
mDevice->IASetInputLayout(mPrivateData->mInputLayout);
|
||||
|
||||
D3D10_VIEWPORT viewport;
|
||||
viewport.MaxDepth = 1;
|
||||
viewport.MinDepth = 0;
|
||||
viewport.Height = mSize.height;
|
||||
viewport.Width = mSize.width;
|
||||
viewport.TopLeftX = 0;
|
||||
viewport.TopLeftY = 0;
|
||||
|
||||
mDevice->RSSetViewports(1, &viewport);
|
||||
}
|
||||
|
||||
ID2D1Factory*
|
||||
DrawTargetD2D::factory()
|
||||
{
|
||||
|
@ -2209,5 +2479,32 @@ DrawTargetD2D::factory()
|
|||
return mFactory;
|
||||
}
|
||||
|
||||
IDWriteFactory*
|
||||
DrawTargetD2D::GetDWriteFactory()
|
||||
{
|
||||
if (mDWriteFactory) {
|
||||
return mDWriteFactory;
|
||||
}
|
||||
|
||||
DWriteCreateFactoryFunc createDWriteFactory;
|
||||
HMODULE dwriteModule = LoadLibraryW(L"dwrite.dll");
|
||||
createDWriteFactory = (DWriteCreateFactoryFunc)
|
||||
GetProcAddress(dwriteModule, "DWriteCreateFactory");
|
||||
|
||||
if (!createDWriteFactory) {
|
||||
gfxWarning() << "Failed to locate DWriteCreateFactory function.";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HRESULT hr = createDWriteFactory(DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory),
|
||||
reinterpret_cast<IUnknown**>(&mDWriteFactory));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
gfxWarning() << "Failed to create DWrite Factory.";
|
||||
}
|
||||
|
||||
return mDWriteFactory;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,12 +52,15 @@
|
|||
#include <unordered_set>
|
||||
#endif
|
||||
|
||||
struct IDWriteFactory;
|
||||
|
||||
namespace mozilla {
|
||||
namespace gfx {
|
||||
|
||||
class SourceSurfaceD2DTarget;
|
||||
class SourceSurfaceD2D;
|
||||
class GradientStopsD2D;
|
||||
class ScaledFontDWrite;
|
||||
|
||||
struct PrivateD3D10DataD2D
|
||||
{
|
||||
|
@ -153,6 +156,7 @@ public:
|
|||
|
||||
static ID2D1Factory *factory();
|
||||
static TemporaryRef<ID2D1StrokeStyle> CreateStrokeStyleForOptions(const StrokeOptions &aStrokeOptions);
|
||||
static IDWriteFactory *GetDWriteFactory();
|
||||
|
||||
operator std::string() const {
|
||||
std::stringstream stream;
|
||||
|
@ -194,12 +198,19 @@ private:
|
|||
// a mask corresponding with the current DrawTarget clip.
|
||||
void EnsureClipMaskTexture();
|
||||
|
||||
bool FillGlyphsManual(ScaledFontDWrite *aFont,
|
||||
const GlyphBuffer &aBuffer,
|
||||
const Color &aColor,
|
||||
IDWriteRenderingParams *aParams,
|
||||
const DrawOptions &aOptions = DrawOptions());
|
||||
|
||||
TemporaryRef<ID2D1RenderTarget> CreateRTForTexture(ID3D10Texture2D *aTexture, SurfaceFormat aFormat);
|
||||
TemporaryRef<ID2D1Geometry> GetClippedGeometry();
|
||||
|
||||
TemporaryRef<ID2D1Brush> CreateBrushForPattern(const Pattern &aPattern, Float aAlpha = 1.0f);
|
||||
|
||||
TemporaryRef<ID3D10Texture1D> CreateGradientTexture(const GradientStopsD2D *aStops);
|
||||
TemporaryRef<ID3D10Texture2D> CreateTextureForAnalysis(IDWriteGlyphRunAnalysis *aAnalysis, const IntRect &aBounds);
|
||||
|
||||
// This creates a partially uploaded bitmap for a SourceSurfaceD2D that is
|
||||
// too big to fit in a bitmap. It adjusts the passed Matrix to accomodate the
|
||||
|
@ -207,6 +218,7 @@ private:
|
|||
TemporaryRef<ID2D1Bitmap> CreatePartialBitmapForSurface(SourceSurfaceD2D *aSurface, Matrix &aMatrix);
|
||||
|
||||
void SetupEffectForRadialGradient(const RadialGradientPattern *aPattern);
|
||||
void SetupStateForRendering();
|
||||
|
||||
static const uint32_t test = 4;
|
||||
|
||||
|
@ -247,6 +259,7 @@ private:
|
|||
bool mClipsArePushed;
|
||||
PrivateD3D10DataD2D *mPrivateData;
|
||||
static ID2D1Factory *mFactory;
|
||||
static IDWriteFactory *mDWriteFactory;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ cbuffer cb0
|
|||
float4 QuadDesc;
|
||||
float4 TexCoords;
|
||||
float4 MaskTexCoords;
|
||||
float4 TextColor;
|
||||
}
|
||||
|
||||
cbuffer cb1
|
||||
|
@ -50,6 +51,12 @@ struct VS_RADIAL_OUTPUT
|
|||
float2 PixelCoord : TEXCOORD1;
|
||||
};
|
||||
|
||||
struct PS_TEXT_OUTPUT
|
||||
{
|
||||
float4 color;
|
||||
float4 alpha;
|
||||
};
|
||||
|
||||
Texture2D tex;
|
||||
Texture2D mask;
|
||||
|
||||
|
@ -113,6 +120,19 @@ BlendState ShadowBlendV
|
|||
RenderTargetWriteMask[0] = 0xF;
|
||||
};
|
||||
|
||||
BlendState bTextBlend
|
||||
{
|
||||
AlphaToCoverageEnable = FALSE;
|
||||
BlendEnable[0] = TRUE;
|
||||
SrcBlend = Src1_Color;
|
||||
DestBlend = Inv_Src1_Color;
|
||||
BlendOp = Add;
|
||||
SrcBlendAlpha = Src1_Alpha;
|
||||
DestBlendAlpha = Inv_Src1_Alpha;
|
||||
BlendOpAlpha = Add;
|
||||
RenderTargetWriteMask[0] = 0x0F; // All
|
||||
};
|
||||
|
||||
VS_OUTPUT SampleTextureVS(float3 pos : POSITION)
|
||||
{
|
||||
VS_OUTPUT Output;
|
||||
|
@ -278,6 +298,26 @@ float4 SampleMaskShadowVPS( VS_OUTPUT In) : SV_Target
|
|||
return outputColor * mask.Sample(sMaskSampler, In.MaskTexCoord).a;
|
||||
};
|
||||
|
||||
PS_TEXT_OUTPUT SampleTextTexturePS( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
PS_TEXT_OUTPUT output;
|
||||
output.color = TextColor;
|
||||
output.alpha.rgba = tex.Sample(sSampler, In.TexCoord).bgrg * TextColor.a;
|
||||
return output;
|
||||
};
|
||||
|
||||
PS_TEXT_OUTPUT SampleTextTexturePSMasked( VS_OUTPUT In) : SV_Target
|
||||
{
|
||||
PS_TEXT_OUTPUT output;
|
||||
|
||||
float maskValue = mask.Sample(sMaskSampler, In.MaskTexCoord).a;
|
||||
|
||||
output.color = TextColor * maskValue;
|
||||
output.alpha.rgba = tex.Sample(sSampler, In.TexCoord).bgrg * TextColor.a * maskValue;
|
||||
|
||||
return output;
|
||||
};
|
||||
|
||||
technique10 SampleTexture
|
||||
{
|
||||
pass P0
|
||||
|
@ -375,4 +415,23 @@ technique10 SampleTextureWithShadow
|
|||
SetGeometryShader(NULL);
|
||||
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleMaskShadowVPS()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
technique10 SampleTextTexture
|
||||
{
|
||||
pass Unmasked
|
||||
{
|
||||
SetBlendState(bTextBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
|
||||
SetGeometryShader(NULL);
|
||||
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleTextTexturePS()));
|
||||
}
|
||||
pass Masked
|
||||
{
|
||||
SetBlendState(bTextBlend, float4( 0.0f, 0.0f, 0.0f, 0.0f ), 0xFFFFFFFF );
|
||||
SetVertexShader(CompileShader(vs_4_0_level_9_3, SampleTextureVS()));
|
||||
SetGeometryShader(NULL);
|
||||
SetPixelShader(CompileShader(ps_4_0_level_9_3, SampleTextTexturePSMasked()));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче