如何使用“广告牌”在屏幕上创建球形物体

时间:2009-11-08 21:10:03

标签: c++ directx

我的任务是让太阳/月球物体在整个时间跨度内流过屏幕(就像在常规日那样)。我可以使用的一个选项是使用“ billboard ”,这是一个始终面向相机的四边形。

我还没有使用许多直接x库或技术。这是我的第一个图形项目。这有什么意义?你如何使用它来在屏幕上移动太阳物体?

谢谢:)这只会在Windows机器上运行,我只能选择直接x( 9 )。

我已经完成了这一半的工作。我有一个太阳图像显示,但无论我的相机指向哪个方向,它都位于我的屏幕前方80%的屏幕上方。我低头朝地面看?那里还有一个巨大的太阳。为什么是这样?这是我用来创建它的代码......

void Sun::DrawSun()
{
    std::wstring hardcoded = L"..\\Data\\sun.png";
    m_SunTexture = MyTextureManager::GetInstance()->GetTextureData(hardcoded.c_str()).m_Texture;


LPD3DXSPRITE sprite = NULL;

if (SUCCEEDED(D3DXCreateSprite(MyRenderer::GetInstance()->GetDevice(), &sprite)))
{
    //created!
}

sprite->Begin(D3DXSPRITE_ALPHABLEND);

D3DXVECTOR3 pos;

pos.x = 40.0f;
pos.y = 20.0f;
pos.z = 20.0f;

HRESULT someHr;
someHr = sprite->Draw(m_SunTexture, NULL, NULL, &pos, 0xFFFFFFFF);
sprite->End();
}

显然,我的位置向量是硬编码的。这是我需要改变的吗?我在文档中注意到D3DXSPRITE_BILLBOARD而不是D3DXSPRITE_ALPHABLEND的可能性,这会有效吗?可以同时使用两者吗?

根据前面文章中提到的教程,D3DXSPRITE是一个2D对象,可能无法在3d世界中显示?什么是更聪明的选择?

3 个答案:

答案 0 :(得分:1)

进行屏幕对齐四边形的最简单方法是使用带有纹理重写的Point Sprites 我从来没有使用DirectX,但在OpenGL中,启用点精灵是2个API调用的问题,看起来像这样。

glEnable(GL_POINT_SPRITE);
glTexEnvi(GL_POINT_SPRITE, GL_COORD_REPLACE, true);

启用此模式后,您绘制单个顶点而不是点,将渲染对齐的四边形屏幕。坐标替换物意味着渲染的四边形用纹理坐标处理。这意味着您可以在四边形上放置任何纹理。通常你会想要一个带有alpha通道的东西无缝融入背景。

在D3D中应该有一种相当简单的方法。另外,如果你写一个着色器,它可能会让你做一些额外的东西,比如丢弃纹理的一些像素。

This tutorial might help
此外,谷歌。

- 的修改
要将四边形转换为任何其他形状,请使用纹理的Alpha通道。如果alpha为0,则像素不可见。您不能将Alpha通道添加到JPEG,但可以将其添加到PNG。这是一个例子:

sun with alpha channel http://www.shiny.co.il/shooshx/sun.png

如果您在photoshop中打开此图片,您会看到背景不可见 如果你在场景中有其他事情,使用alpha混合可能会导致一些问题,所以如果发生这种情况,你可以写一个简单的片段着色器,丢弃alpha == 0的像素。

答案 1 :(得分:0)

是的,通常会使用广告牌。计算广告牌角落的坐标和纹理参数非常简单。纹理本身可以使用其他技术进行渲染(例如,在系统ram中的应用程序中)。

它很简单,可以拍摄相机的向右和向上矢量,然后从想要渲染对象的世界坐标的中心点添加/分割(适当缩放)。

答案 2 :(得分:0)

好吧我不是直接的x专家,所以我会假设一些事情。

首先我假设您有某种DrawQuad()函数,它在渲染类中包含4个角和一个纹理。

首先,我们要获取当前的视口矩阵

D3DMATRIX mat;
hr = m_Renderer->GetRenderDevice()->GetTransform(D3DTS_VIEW,&mat);

让我们设置一些任意大小

float size = 20.0f;

现在我们需要计算向上单位向量和右单位向量的两个向量。

D3DXVECTOR3 rightVect;
D3DXVECTOR3 viewMatrixA(mat._11,mat._21,mat._31);
D3DXVECTOR3 viewMatrixB(mat._12,mat._22,mat._32);
D3DXVec3Normalize(&rightVect, &viewMatrixA);
rightVect = rightVect * size * 0.5f;
D3DXVECTOR3 upVect;
D3DXVec3Normalize(&upVect, &viewMatrixB);
upVect = upVect * size * 0.5f;

现在我们需要为我们的对象定义一个位置,我只是在原点。

D3DXVECTOR3 loc(0.0f, 0.0f, 0.0f);

让我们加载太阳纹理:

m_SunTexture = <insert magic texture load>

现在让我们弄清楚4个角落。

D3DXVECTOR3 upperLeft = loc - rightVect;
D3DXVECTOR3 upperRight = loc + upVect;
D3DXVECTOR3 lowerRight = loc-upVect;
D3DXVECTOR3 lowerLeft= loc + rightVect;

让我们画四边形。我假设这个功能存在,否则你需要做 一些顶点绘图。

m_Renderer->DrawQuad(
    upperLeft.x, upperLeft.y, upperLeft.z,
    upperRight.x, upperRight.y, upperRight.z,
    lowerRight.x, lowerRight.y, lowerRight.z,
    lowerLeft.x, lowerLeft.y, lowerLeft.z, m_SunTexture);

享受:)!