lighting
This commit is contained in:
parent
8833c106a8
commit
96e0a3ab7b
153
main.cpp
153
main.cpp
@ -12,7 +12,8 @@ ID3D10Texture2D * g_pDepthStencil = NULL;
|
|||||||
ID3D10RenderTargetView * g_pRenderTargetView = NULL;
|
ID3D10RenderTargetView * g_pRenderTargetView = NULL;
|
||||||
ID3D10DepthStencilView * g_pDepthStencilView = NULL;
|
ID3D10DepthStencilView * g_pDepthStencilView = NULL;
|
||||||
ID3D10Effect * g_pEffect = NULL;
|
ID3D10Effect * g_pEffect = NULL;
|
||||||
ID3D10EffectTechnique * g_pTechnique = NULL;
|
ID3D10EffectTechnique * g_pTechniqueRender = NULL;
|
||||||
|
ID3D10EffectTechnique * g_pTechniqueRenderLight = NULL;
|
||||||
ID3D10InputLayout * g_pVertexLayout = NULL;
|
ID3D10InputLayout * g_pVertexLayout = NULL;
|
||||||
ID3D10Buffer * g_pVertexBuffer = NULL;
|
ID3D10Buffer * g_pVertexBuffer = NULL;
|
||||||
ID3D10Buffer * g_pIndexBuffer = NULL;
|
ID3D10Buffer * g_pIndexBuffer = NULL;
|
||||||
@ -20,6 +21,9 @@ ID3D10Buffer * g_pIndexBuffer = NULL;
|
|||||||
ID3D10EffectMatrixVariable * g_pWorldVariable = NULL;
|
ID3D10EffectMatrixVariable * g_pWorldVariable = NULL;
|
||||||
ID3D10EffectMatrixVariable * g_pViewVariable = NULL;
|
ID3D10EffectMatrixVariable * g_pViewVariable = NULL;
|
||||||
ID3D10EffectMatrixVariable * g_pProjectionVariable = NULL;
|
ID3D10EffectMatrixVariable * g_pProjectionVariable = NULL;
|
||||||
|
ID3D10EffectVectorVariable * g_pLightDirVariable = NULL;
|
||||||
|
ID3D10EffectVectorVariable * g_pLightColorVariable = NULL;
|
||||||
|
ID3D10EffectVectorVariable * g_pOutputColorVariable = NULL;
|
||||||
D3DXMATRIX g_World1;
|
D3DXMATRIX g_World1;
|
||||||
D3DXMATRIX g_World2;
|
D3DXMATRIX g_World2;
|
||||||
D3DXMATRIX g_View;
|
D3DXMATRIX g_View;
|
||||||
@ -32,7 +36,7 @@ void Render();
|
|||||||
|
|
||||||
struct SimpleVertex {
|
struct SimpleVertex {
|
||||||
D3DXVECTOR3 Pos;
|
D3DXVECTOR3 Pos;
|
||||||
D3DXVECTOR4 Color;
|
D3DXVECTOR3 Normal;
|
||||||
};
|
};
|
||||||
|
|
||||||
void print(LPCSTR fmt, ...)
|
void print(LPCSTR fmt, ...)
|
||||||
@ -265,23 +269,27 @@ HRESULT InitDirect3DDevice()
|
|||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pTechnique = g_pEffect->GetTechniqueByName("Render");
|
g_pTechniqueRender = g_pEffect->GetTechniqueByName("Render");
|
||||||
|
g_pTechniqueRenderLight = g_pEffect->GetTechniqueByName("RenderLight");
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
|
|
||||||
g_pWorldVariable = g_pEffect->GetVariableByName("World")->AsMatrix();
|
g_pWorldVariable = g_pEffect->GetVariableByName("World")->AsMatrix();
|
||||||
g_pViewVariable = g_pEffect->GetVariableByName("View")->AsMatrix();
|
g_pViewVariable = g_pEffect->GetVariableByName("View")->AsMatrix();
|
||||||
g_pProjectionVariable = g_pEffect->GetVariableByName("Projection")->AsMatrix();
|
g_pProjectionVariable = g_pEffect->GetVariableByName("Projection")->AsMatrix();
|
||||||
|
g_pLightDirVariable = g_pEffect->GetVariableByName("vLightDir")->AsVector();
|
||||||
|
g_pLightColorVariable = g_pEffect->GetVariableByName("vLightColor")->AsVector();
|
||||||
|
g_pOutputColorVariable = g_pEffect->GetVariableByName("vOutputColor")->AsVector();
|
||||||
|
|
||||||
// input layout
|
// input layout
|
||||||
D3D10_INPUT_ELEMENT_DESC layout[] = {
|
D3D10_INPUT_ELEMENT_DESC layout[] = {
|
||||||
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT , 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
|
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0 , D3D10_INPUT_PER_VERTEX_DATA, 0},
|
||||||
{"COLOR" , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0},
|
{"NORMAL" , 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D10_INPUT_PER_VERTEX_DATA, 0},
|
||||||
};
|
};
|
||||||
UINT numElements = (sizeof (layout)) / (sizeof (layout[0]));
|
UINT numElements = (sizeof (layout)) / (sizeof (layout[0]));
|
||||||
|
|
||||||
D3D10_PASS_DESC passDesc;
|
D3D10_PASS_DESC passDesc;
|
||||||
g_pTechnique->GetPassByIndex(0)->GetDesc(&passDesc);
|
g_pTechniqueRender->GetPassByIndex(0)->GetDesc(&passDesc);
|
||||||
print("pass desc: `%s`\n", passDesc.Name);
|
print("pass desc: `%s`\n", passDesc.Name);
|
||||||
|
|
||||||
hr = g_pd3dDevice->CreateInputLayout(layout, numElements,
|
hr = g_pd3dDevice->CreateInputLayout(layout, numElements,
|
||||||
@ -301,17 +309,39 @@ HRESULT InitDirect3DDevice()
|
|||||||
|
|
||||||
// vertex buffer
|
// vertex buffer
|
||||||
SimpleVertex vertices[] = {
|
SimpleVertex vertices[] = {
|
||||||
{ D3DXVECTOR3(-1.0f, 1.0f, -1.0f), D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f) },
|
{ D3DXVECTOR3(-1.0f, 1.0f, -1.0f), D3DXVECTOR3( 0.0f, 1.0f, 0.0f) },
|
||||||
{ D3DXVECTOR3( 1.0f, 1.0f, -1.0f), D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f) },
|
{ D3DXVECTOR3( 1.0f, 1.0f, -1.0f), D3DXVECTOR3( 0.0f, 1.0f, 0.0f) },
|
||||||
{ D3DXVECTOR3( 1.0f, 1.0f, 1.0f), D3DXVECTOR4(0.0f, 1.0f, 1.0f, 1.0f) },
|
{ D3DXVECTOR3( 1.0f, 1.0f, 1.0f), D3DXVECTOR3( 0.0f, 1.0f, 0.0f) },
|
||||||
{ D3DXVECTOR3(-1.0f, 1.0f, 1.0f), D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f) },
|
{ D3DXVECTOR3(-1.0f, 1.0f, 1.0f), D3DXVECTOR3( 0.0f, 1.0f, 0.0f) },
|
||||||
{ D3DXVECTOR3(-1.0f, -1.0f, -1.0f), D3DXVECTOR4(1.0f, 0.0f, 1.0f, 1.0f) },
|
|
||||||
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f), D3DXVECTOR4(1.0f, 1.0f, 0.0f, 1.0f) },
|
{ D3DXVECTOR3(-1.0f, -1.0f, -1.0f), D3DXVECTOR3( 0.0f, -1.0f, 0.0f) },
|
||||||
{ D3DXVECTOR3( 1.0f, -1.0f, 1.0f), D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f) },
|
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f), D3DXVECTOR3( 0.0f, -1.0f, 0.0f) },
|
||||||
{ D3DXVECTOR3(-1.0f, -1.0f, 1.0f), D3DXVECTOR4(0.0f, 0.0f, 0.0f, 1.0f) },
|
{ D3DXVECTOR3( 1.0f, -1.0f, 1.0f), D3DXVECTOR3( 0.0f, -1.0f, 0.0f) },
|
||||||
|
{ D3DXVECTOR3(-1.0f, -1.0f, 1.0f), D3DXVECTOR3( 0.0f, -1.0f, 0.0f) },
|
||||||
|
|
||||||
|
{ D3DXVECTOR3(-1.0f, -1.0f, 1.0f), D3DXVECTOR3(-1.0f, 0.0f, 0.0f) },
|
||||||
|
{ D3DXVECTOR3(-1.0f, -1.0f, -1.0f), D3DXVECTOR3(-1.0f, 0.0f, 0.0f) },
|
||||||
|
{ D3DXVECTOR3(-1.0f, 1.0f, -1.0f), D3DXVECTOR3(-1.0f, 0.0f, 0.0f) },
|
||||||
|
{ D3DXVECTOR3(-1.0f, 1.0f, 1.0f), D3DXVECTOR3(-1.0f, 0.0f, 0.0f) },
|
||||||
|
|
||||||
|
{ D3DXVECTOR3( 1.0f, -1.0f, 1.0f), D3DXVECTOR3( 1.0f, 0.0f, 0.0f) },
|
||||||
|
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f), D3DXVECTOR3( 1.0f, 0.0f, 0.0f) },
|
||||||
|
{ D3DXVECTOR3( 1.0f, 1.0f, -1.0f), D3DXVECTOR3( 1.0f, 0.0f, 0.0f) },
|
||||||
|
{ D3DXVECTOR3( 1.0f, 1.0f, 1.0f), D3DXVECTOR3( 1.0f, 0.0f, 0.0f) },
|
||||||
|
|
||||||
|
{ D3DXVECTOR3(-1.0f, -1.0f, -1.0f), D3DXVECTOR3( 0.0f, 0.0f, -1.0f) },
|
||||||
|
{ D3DXVECTOR3( 1.0f, -1.0f, -1.0f), D3DXVECTOR3( 0.0f, 0.0f, -1.0f) },
|
||||||
|
{ D3DXVECTOR3( 1.0f, 1.0f, -1.0f), D3DXVECTOR3( 0.0f, 0.0f, -1.0f) },
|
||||||
|
{ D3DXVECTOR3(-1.0f, 1.0f, -1.0f), D3DXVECTOR3( 0.0f, 0.0f, -1.0f) },
|
||||||
|
|
||||||
|
{ D3DXVECTOR3(-1.0f, -1.0f, 1.0f), D3DXVECTOR3( 0.0f, 0.0f, 1.0f) },
|
||||||
|
{ D3DXVECTOR3( 1.0f, -1.0f, 1.0f), D3DXVECTOR3( 0.0f, 0.0f, 1.0f) },
|
||||||
|
{ D3DXVECTOR3( 1.0f, 1.0f, 1.0f), D3DXVECTOR3( 0.0f, 0.0f, 1.0f) },
|
||||||
|
{ D3DXVECTOR3(-1.0f, 1.0f, 1.0f), D3DXVECTOR3( 0.0f, 0.0f, 1.0f) },
|
||||||
};
|
};
|
||||||
|
int vertices_length = (sizeof (vertices)) / (sizeof (vertices[0]));
|
||||||
bd.Usage = D3D10_USAGE_DEFAULT;
|
bd.Usage = D3D10_USAGE_DEFAULT;
|
||||||
bd.ByteWidth = (sizeof (SimpleVertex)) * 8;
|
bd.ByteWidth = (sizeof (SimpleVertex)) * vertices_length;
|
||||||
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
|
||||||
bd.CPUAccessFlags = 0;
|
bd.CPUAccessFlags = 0;
|
||||||
bd.MiscFlags = 0;
|
bd.MiscFlags = 0;
|
||||||
@ -330,23 +360,24 @@ HRESULT InitDirect3DDevice()
|
|||||||
3,1,0,
|
3,1,0,
|
||||||
2,1,3,
|
2,1,3,
|
||||||
|
|
||||||
0,5,4,
|
|
||||||
1,5,0,
|
|
||||||
|
|
||||||
3,4,7,
|
|
||||||
0,4,3,
|
|
||||||
|
|
||||||
1,6,5,
|
|
||||||
2,6,1,
|
|
||||||
|
|
||||||
2,7,6,
|
|
||||||
3,7,2,
|
|
||||||
|
|
||||||
6,4,5,
|
6,4,5,
|
||||||
7,4,6,
|
7,4,6,
|
||||||
|
|
||||||
|
11,9,8,
|
||||||
|
10,9,11,
|
||||||
|
|
||||||
|
14,12,13,
|
||||||
|
15,12,14,
|
||||||
|
|
||||||
|
19,17,16,
|
||||||
|
18,17,19,
|
||||||
|
|
||||||
|
22,20,21,
|
||||||
|
23,20,22
|
||||||
};
|
};
|
||||||
|
int indices_length = (sizeof (indices)) / (sizeof (indices[0]));
|
||||||
bd.Usage = D3D10_USAGE_DEFAULT;
|
bd.Usage = D3D10_USAGE_DEFAULT;
|
||||||
bd.ByteWidth = (sizeof (DWORD)) * 36;
|
bd.ByteWidth = (sizeof (DWORD)) * indices_length;
|
||||||
bd.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
bd.BindFlags = D3D10_BIND_INDEX_BUFFER;
|
||||||
bd.CPUAccessFlags = 0;
|
bd.CPUAccessFlags = 0;
|
||||||
bd.MiscFlags = 0;
|
bd.MiscFlags = 0;
|
||||||
@ -384,7 +415,7 @@ HRESULT InitDirect3DDevice()
|
|||||||
void Render()
|
void Render()
|
||||||
{
|
{
|
||||||
static float t = 0.0f;
|
static float t = 0.0f;
|
||||||
if (0) {
|
if (1) {
|
||||||
t += (float)D3DX_PI * 0.0125f;
|
t += (float)D3DX_PI * 0.0125f;
|
||||||
} else {
|
} else {
|
||||||
static DWORD dwTimeStart = 0;
|
static DWORD dwTimeStart = 0;
|
||||||
@ -397,44 +428,66 @@ void Render()
|
|||||||
// first cube
|
// first cube
|
||||||
D3DXMatrixRotationY(&g_World1, t);
|
D3DXMatrixRotationY(&g_World1, t);
|
||||||
|
|
||||||
// second cube
|
// lights
|
||||||
D3DXMATRIX mTranslate;
|
D3DXVECTOR4 vLightDirs[2] = {
|
||||||
D3DXMATRIX mOrbit;
|
D3DXVECTOR4(-0.577f, 0.577f, -0.577f, 1.0f),
|
||||||
D3DXMATRIX mSpin;
|
D3DXVECTOR4(0.0f, 0.0f, -1.0f, 1.0f),
|
||||||
D3DXMATRIX mScale;
|
};
|
||||||
D3DXMatrixRotationZ(&mSpin, -t);
|
D3DXVECTOR4 vLightColors[2] = {
|
||||||
D3DXMatrixRotationY(&mOrbit, -t * 2.0f);
|
D3DXVECTOR4(0.0f, 0.5f, 0.5f, 1.0f),
|
||||||
D3DXMatrixTranslation(&mTranslate, -4.0f, 0.0f, 0.0f);
|
D3DXVECTOR4(0.5f, 0.0f, 0.0f, 1.0f)
|
||||||
D3DXMatrixScaling(&mScale, 0.3f, 0.3f, 0.3f);
|
};
|
||||||
|
|
||||||
D3DXMatrixMultiply(&g_World2, &mScale, &mSpin);
|
// rotate the second light around the origin
|
||||||
D3DXMatrixMultiply(&g_World2, &g_World2, &mTranslate);
|
D3DXMATRIX mRotate;
|
||||||
D3DXMatrixMultiply(&g_World2, &g_World2, &mOrbit);
|
D3DXVECTOR4 vOutDir;
|
||||||
|
D3DXMatrixRotationY(&mRotate, -2.0f * t);
|
||||||
|
D3DXVec3Transform(&vLightDirs[1], (D3DXVECTOR3 *)&vLightDirs[1], &mRotate);
|
||||||
|
|
||||||
|
D3DXMatrixRotationY(&mRotate, 0.4f * t);
|
||||||
|
D3DXVec3Transform(&vLightDirs[0], (D3DXVECTOR3 *)&vLightDirs[0], &mRotate);
|
||||||
|
|
||||||
|
// clear
|
||||||
float ClearColor[4] = { 0.0f, 0.125f, 0.6f, 1.0f };
|
float ClearColor[4] = { 0.0f, 0.125f, 0.6f, 1.0f };
|
||||||
g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetView, ClearColor);
|
g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetView, ClearColor);
|
||||||
g_pd3dDevice->ClearDepthStencilView(g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
|
g_pd3dDevice->ClearDepthStencilView(g_pDepthStencilView, D3D10_CLEAR_DEPTH, 1.0f, 0);
|
||||||
|
|
||||||
|
// matrices
|
||||||
g_pViewVariable->SetMatrix((float *)&g_View);
|
g_pViewVariable->SetMatrix((float *)&g_View);
|
||||||
g_pProjectionVariable->SetMatrix((float *)&g_Projection);
|
g_pProjectionVariable->SetMatrix((float *)&g_Projection);
|
||||||
|
g_pWorldVariable->SetMatrix((float *)&g_World1);
|
||||||
|
|
||||||
D3D10_TECHNIQUE_DESC techDesc;
|
// lights
|
||||||
g_pTechnique->GetDesc(&techDesc);
|
g_pLightDirVariable->SetFloatVectorArray((float *)vLightDirs, 0, 2);
|
||||||
|
g_pLightColorVariable->SetFloatVectorArray((float *)vLightColors, 0, 2);
|
||||||
|
|
||||||
// render first cube
|
// render first cube
|
||||||
g_pWorldVariable->SetMatrix((float *)&g_World1);
|
D3D10_TECHNIQUE_DESC techDesc;
|
||||||
for(UINT p = 0; p < techDesc.Passes; p++) {
|
g_pTechniqueRender->GetDesc(&techDesc);
|
||||||
g_pTechnique->GetPassByIndex(p)->Apply(0);
|
for (UINT p = 0; p < techDesc.Passes; p++) {
|
||||||
|
g_pTechniqueRender->GetPassByIndex(p)->Apply(0);
|
||||||
g_pd3dDevice->DrawIndexed(36, 0, 0);
|
g_pd3dDevice->DrawIndexed(36, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// render second cube
|
// render the lights
|
||||||
g_pWorldVariable->SetMatrix((float *)&g_World2);
|
for (int m = 0; m < 2; m++) {
|
||||||
for(UINT p = 0; p < techDesc.Passes; p++) {
|
D3DXMATRIX mLight;
|
||||||
g_pTechnique->GetPassByIndex(p)->Apply(0);
|
D3DXMATRIX mLightScale;
|
||||||
|
D3DXVECTOR3 vLightPos = vLightDirs[m] * 4.0f;
|
||||||
|
D3DXMatrixTranslation( &mLight, vLightPos.x, vLightPos.y, vLightPos.z );
|
||||||
|
D3DXMatrixScaling( &mLightScale, 0.2f, 0.2f, 0.2f );
|
||||||
|
mLight = mLightScale * mLight;
|
||||||
|
|
||||||
|
g_pWorldVariable->SetMatrix((float *)&mLight);
|
||||||
|
g_pOutputColorVariable->SetFloatVector((float *)&vLightColors[m]);
|
||||||
|
|
||||||
|
g_pTechniqueRenderLight->GetDesc( &techDesc );
|
||||||
|
for (UINT p = 0; p < techDesc.Passes; p++) {
|
||||||
|
g_pTechniqueRenderLight->GetPassByIndex(p)->Apply(0);
|
||||||
g_pd3dDevice->DrawIndexed(36, 0, 0);
|
g_pd3dDevice->DrawIndexed(36, 0, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// present
|
||||||
g_pSwapChain->Present(0, 0);
|
g_pSwapChain->Present(0, 0);
|
||||||
}
|
}
|
||||||
|
|||||||
50
main.fx
50
main.fx
@ -2,25 +2,47 @@ matrix World;
|
|||||||
matrix View;
|
matrix View;
|
||||||
matrix Projection;
|
matrix Projection;
|
||||||
|
|
||||||
struct VS_OUTPUT
|
float4 vLightDir[2];
|
||||||
|
float4 vLightColor[2];
|
||||||
|
float4 vOutputColor;
|
||||||
|
|
||||||
|
struct VS_INPUT
|
||||||
{
|
{
|
||||||
float4 Pos: SV_POSITION;
|
float4 Pos : POSITION;
|
||||||
float4 Color : COLOR0;
|
float4 Normal : NORMAL;
|
||||||
};
|
};
|
||||||
|
|
||||||
VS_OUTPUT VS(float4 Pos : POSITION, float4 Color : COLOR)
|
struct PS_INPUT
|
||||||
{
|
{
|
||||||
VS_OUTPUT output = (VS_OUTPUT)0;
|
float4 Pos : SV_POSITION;
|
||||||
output.Pos = mul(Pos, World);
|
float4 Normal : TEXCOORD0;
|
||||||
|
};
|
||||||
|
|
||||||
|
PS_INPUT VS(VS_INPUT input)
|
||||||
|
{
|
||||||
|
PS_INPUT output = (PS_INPUT)0;
|
||||||
|
output.Pos = mul(input.Pos, World);
|
||||||
output.Pos = mul(output.Pos, View);
|
output.Pos = mul(output.Pos, View);
|
||||||
output.Pos = mul(output.Pos, Projection);
|
output.Pos = mul(output.Pos, Projection);
|
||||||
output.Color = Color;
|
output.Normal = mul(input.Normal, World);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
float4 PS(VS_OUTPUT input) : SV_Target
|
float4 PS(PS_INPUT input) : SV_Target
|
||||||
{
|
{
|
||||||
return input.Color;
|
float4 finalColor = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < 2; i++) {
|
||||||
|
finalColor += saturate(dot((float3)vLightDir[i], input.Normal) * vLightColor[i]);
|
||||||
|
}
|
||||||
|
finalColor.a = 1;
|
||||||
|
|
||||||
|
return finalColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
float4 PSSolid(PS_INPUT input) : SV_Target
|
||||||
|
{
|
||||||
|
return vOutputColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
technique10 Render
|
technique10 Render
|
||||||
@ -32,3 +54,13 @@ technique10 Render
|
|||||||
SetPixelShader(CompileShader(ps_4_0, PS()));
|
SetPixelShader(CompileShader(ps_4_0, PS()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
technique10 RenderLight
|
||||||
|
{
|
||||||
|
pass P0
|
||||||
|
{
|
||||||
|
SetVertexShader(CompileShader(vs_4_0, VS()));
|
||||||
|
SetGeometryShader(NULL);
|
||||||
|
SetPixelShader(CompileShader(ps_4_0, PSSolid()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user