Related
First for the part that does work using XMMATH where data.model is a XMMatrix:
static auto model_matrix = DirectX::XMMatrixIdentity();
static auto pos = DirectX::XMVectorSet(0.0f, 0.0f, -10.0f, 0.0f);
static auto focus = DirectX::XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f);
static auto up = DirectX::XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
static auto view_matrix = DirectX::XMMatrixLookAtLH(pos, focus, up);
static auto proj_matrix = DirectX::XMMatrixPerspectiveFovLH(glm::radians(45.0f), 16.0f / 9.0f, 0.1f, 10000.0f);
building the mvp:
data.model = model_matrix * view_matrix * proj_matrix;
data.model = DirectX::XMMatrixTranspose(data.model);
when I hand the data.model over to my HLSL shader, everything works fine and and I can change the pos vector to look at my cube from different angles. HLSL vertex shader:
cbuffer myCbuffer : register(b0) {
float4x4 mat;
}
float4 main(float3 pos : POSITION) : SV_POSITION
{
return mul(float4(pos, 1), mat);
}
Now when I try to make something similar using GLM (I changed the type of data.model to be a glm::mat4 ):
auto gl_m = glm::mat4(1.0f);
static auto gl_pos = glm::vec3(0.0f, 0.0f, -10.0f);
static auto gl_focus = glm::vec3(0.0f, 0.0f, 0.0f);
static auto gl_up = glm::vec3(0.0f, 1.0f, 0.0f);
auto gl_v = glm::lookAtLH(gl_pos, gl_focus, gl_up);
auto gl_p = glm::perspectiveFovLH_ZO(glm::radians(45.0f), 1280.0f, 720.0f, 0.1f, 10000.0f);
building the MVP:
data.model = gl_m * gl_v * gl_p;
Now when I pass this to data.model the cube does get rendered but the whole screen is filled black. (my cube is black and the clear color is light-blue, so I think it's rendering the cube but really close or inside it).
I don't know where to look on how to fix this, the projection matrix should be in the correct clipping space since I'm using perspectiveFovLH_ZO, the ZO fixes the clipping space to [0..1]. It could be how the HLSL shader float4x4 deals with the glm::mat4, but both are column major I believe so no need to transpose.
It might have something to do with the rasterizer culling settings and the FrontCounterClockwise setting, but I'm fairly new to DirectX and don't know what it does exactly.
D3D11_RASTERIZER_DESC raster_desc = {0};
raster_desc.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
raster_desc.CullMode = D3D11_CULL_MODE::D3D11_CULL_NONE;
raster_desc.FrontCounterClockwise = false;
d3device->CreateRasterizerState(&raster_desc, rasterize_state.GetAddressOf());
Any help is appreciated, let me know if I forgot anything.
Managed to fix it (seems like a bandaid fix but I'll work with it for now).
After I build the mvp I added:
gl_mvp[3][3] = -10.0f;
gl_mvp = glm::transpose(gl_mvp);
the -10 is the z coordinate of the camera position (the same one you pass as the first argument to glm::lookAtLH). I thought HLSL/DirectX matched the column-major GLM matrices but apparently not, it needed the extra transpose call. I'm not sure why that is and what the bottom left element of the MVP is that it has to match the positional z, maybe someone with a better understanding of the math behind it can clarify.
Removed gl_mvp[3][3] = -10.0f; since it's a bad fix, instead I got this now:
changed both the lookAtLH and PerspectiveFovLH_ZO to their RH variants.
Also changed the order of building the MVP from M * V * P to P * V * M.
New code that seems to work well (even flying around using my Camera class):
auto gl_m = glm::mat4(1.0f);
auto gl_v = glm::lookAtRH(position, position + dir, {0, 1, 0});
auto gl_p = glm::perspectiveFovRH_ZO(glm::radians(FOV), 1280.0f, 720.0f, 0.1f, 10000.0f);
glm::mat4 gl_mvp = gl_p * gl_v * gl_m;
return glm::transpose(gl_mvp);
It's a bit different from the previous code cause this is inside my Camera class, so position, dir and FOV are variables I keep track off but you get the idea. Passed this return result to my HLSL shader and all seems well so far.
I have a vertex buffer created as follows:
ID3D10Buffer * VertexBuffer;
Vertex_PosCol * Vertices;
D3D10_SUBRESOURCE_DATA VertexData;
Vertices = new Vertex_PosCol[VerticeCount];
Vertices[0].Position = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
Vertices[0].Color = D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f);
Vertices[1].Position = D3DXVECTOR3(-1.0f, 2.0f, 0.0f);
Vertices[1].Color = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);
Vertices[2].Position = D3DXVECTOR3(1.0f, 2.0f, 0.0f);
Vertices[2].Color = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);
Vertices[3].Position = D3DXVECTOR3(2.0f, 1.0f, 0.0f);
Vertices[3].Color = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 1.0f);
Vertices[4].Position = D3DXVECTOR3(2.0f, -1.0f, 0.0f);
Vertices[4].Color = D3DXVECTOR4(1.0f, 1.0f, 0.0f, 1.0f);
Vertices[5].Position = D3DXVECTOR3(1.0f, -2.0f, 0.0f);
Vertices[5].Color = D3DXVECTOR4(0.0f, 1.0f, 1.0f, 1.0f);
Vertices[6].Position = D3DXVECTOR3(-1.0f, -2.0f, 0.0f);
Vertices[6].Color = D3DXVECTOR4(1.0f, 0.0f, 1.0f, 1.0f);
Vertices[7].Position = D3DXVECTOR3(-2.0f, -1.0f, 0.0f);
Vertices[7].Color = D3DXVECTOR4(1.0f, 0.0f, 0.0f, 1.0f);
Vertices[8].Position = D3DXVECTOR3(-2.0f, 1.0f, 0.0f);
Vertices[8].Color = D3DXVECTOR4(0.0f, 1.0f, 0.0f, 1.0f);
D3D10_BUFFER_DESC vbd;
vbd.Usage = D3D10_USAGE_DYNAMIC;
vbd.ByteWidth = sizeof(Vertex_PosCol) * VerticeCount;
vbd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
vbd.MiscFlags = 0;
VertexData.pSysMem = Vertices;
HRESULT result = this->GDM.Device->CreateBuffer(&vbd, &VertexData, &VertexBuffer);
I am currently using ID3D10Buffer::Map() to update my vertices which works fine right now. This issue is that my application may require large amounts of vertex updates in the future but not every vertex in every mesh/buffer(one day, a buffer will hold multiple meshes). As far as I have looked everywhere says to use ID3D10Device::CopySubresourceRegion(). That is exactly what i want to do! Except I can't get it to work. I simply don't understand how it works. I read Microsoft's page on it and it's not directed towards vertex buffers. I was hoping that someone can explain to me how to implement it in regards to vertex buffers and/or link me to some helpful resources that do the same.
It's not quite clear what you're asking, because you cannot update buffer with ID3D10Device::CopySubresourceRegion(). I'm trying to clarify resource copying and resource updating in my answer.
Updating resource
By "updating" resource we usually mean transferring data from system memory to GPU memory1, with overwriting.
For updating resource you use either ID3D10Buffer::Map()/ID3D10Buffer::Unmap() pair or ID3D10Device::UpdateSubresource() method. Which is better to use depends on resource properties and update frequency (read Nvidia's "canonical" paper).
Usage is really straightforward. Here is a case for simple 1D buffer, such as vertex buffer.
// Source array/vector (srcData): [xxxxDATADATADATADATADATAxxxxxxxxxxx]
// ^ ^
// srcBegin (srcBegin+bytesToCopy)
//
// Destination buffer (pBuffer): [xxDATADATADATADATADATAxxxxxxxxxxxxx]
// ^ ^
// destinationBegin (destinationBegin+bytesToCopy)
D3D11_BOX box{};
box.left = destinationBegin;
box.right = destinationBegin + bytesToCopy;
box.top = 0;
box.bottom = 1;
box.front = 0;
box.back = 1;
Device->UpdateSubresource(pBuffer, 0, &box, (uint8_t*)srcData+srcBegin, 0, 0);
Copying resource
As name states, ID3D10Device::CopySubresourceRegion() method is suited for copying data between two resources (such as buffers or textures). Simplifying, you can think of it as of copying chunks of data inside videocard's memory (but that's not always true). You cannot "update" GPU memory with that method, as data being copied already there.
Here is a simple example:
D3D11_BOX srcBox{};
srcBox.left = srcBegin;
srcBox.right = srcBegin + size;
srcBox.top = 0;
srcBox.bottom = 1;
srcBox.front = 0;
srcBox.back = 1;
Device->CopySubresourceRegion(pDst, 0, dstBegin, 0, 0, pSrc, 0, &srcBox);
Hope it helps.
BTW, there is no any reason to learn DirectX 10 in 2013. You can start with DirectX 11, its API is almost the same, but more features.
1 This explanation is overly simplified. We can never be sure where given resource resides (GPU, system memory, whatever storage), as it is up to driver implementer to decide where when and which kinds of resources to store.
tip: size is the amount of verts times their bytesize each
D3D11_BOX srcBox{};
srcBox.left = srcBegin;
srcBox.right = srcBegin + size; <-here
srcBox.top = 0;
srcBox.bottom = 1;
srcBox.front = 0;
srcBox.back = 1;
Device->CopySubresourceRegion(pDst, 0, dstBegin, 0, 0, pSrc, 0, &srcBox);
I'm trying to make a rather basic 2D Engine with Direct3D.
I made a LoadImage() function which stores all the rather static behaviour of the image in an object. (Shaders, Vertexbuffers, Samplers etc)
I am planning to do the positioning of the vertices with matrices in constant buffers.
However, I would also like to have a DrawImage() function, which would have a parameter to tell what part of the texture should be drawn (clipped), so I would have to update the texture coordinates.
Since the vertexbuffer is already pre-defined, I wondered if there is a way to update texture coordinates via a constantbuffer that would be sent to the vertexshader?
I hope my question is clear enough, if you have any doubts look at the code below.
bool GameManager::GMLoadImage(Image* pImage, const char* pkcFilePath, ImageDesc* pImDesc)
{
pImage = new Image();
ID3D11ShaderResourceView* pColorMap = (pImage)->GetpColorMap();
/// CREATE SHADER RESOURCE VIEW (from file) ///
HRESULT result = D3DX11CreateShaderResourceViewFromFileA(m_pDevice,
pkcFilePath,
0,
0,
&pColorMap,
0);
if (FAILED(result)) {
MessageBoxA(NULL,"Error loading ShaderResourceView from file","Error",MB_OK);
return false;
}
/// RECEIVE TEXTURE DESC ///
ID3D11Resource* pColorTex;
pColorMap->GetResource(&pColorTex);
((ID3D11Texture2D*)pColorTex)->GetDesc(&((pImage)->GetColorTexDesc()));
pColorTex->Release();
/// CREATE VERTEX BUFFER ///
D3D11_TEXTURE2D_DESC colorTexDesc = pImage->GetColorTexDesc();
float halfWidth = static_cast<float>(colorTexDesc.Width)/2.0f;
float halfHeight = static_cast<float>(colorTexDesc.Height)/2.0f;
Vertex.PosTex vertices[]=
{
{XMFLOAT3( halfWidth, halfHeight, 1.0f ), XMFLOAT2( 1.0f, 0.0f )},
{XMFLOAT3( halfWidth, -halfHeight, 1.0f ), XMFLOAT2( 1.0f, 1.0f )},
{XMFLOAT3( -halfWidth, -halfHeight, 1.0f ), XMFLOAT2( 0.0f, 1.0f )},
{XMFLOAT3( -halfWidth, -halfHeight, 1.0f ), XMFLOAT2( 0.0f, 1.0f )},
{XMFLOAT3( -halfWidth, halfHeight, 1.0f ), XMFLOAT2( 0.0f, 0.0f )},
{XMFLOAT3( halfWidth, halfHeight, 1.0f ), XMFLOAT2( 1.0f, 0.0f )}
};
D3D11_BUFFER_DESC vertexDesc;
ZeroMemory(&vertexDesc,sizeof(vertexDesc));
vertexDesc.Usage = D3D11_USAGE_DEFAULT;
vertexDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexDesc.ByteWidth = sizeof(Vertex.PosTex)*6;
D3D11_SUBRESOURCE_DATA resourceData;
resourceData.pSysMem = vertices;
ID3D11Buffer* pVBuffer = pImage->GetpVertexBuffer();
result = m_pDevice->CreateBuffer(&vertexDesc,&resourceData,&pVBuffer);
if (FAILED(result))
{
MessageBoxA(NULL,"Error Creating VBuffer","Error",MB_OK);
return false;
}
/// SET POINTER TO IMAGEDESC
ImageDesc* pThisImDesc = pImage->GetpImageDesc();
pThisImDesc = pImDesc;
return true;
}
bool GameManager::GMDrawImage(Image* pImage, const CLIPRECT& rkClip)
{
ImageDesc* thisImDesc = pImage->GetpImageDesc();
if ( (thisImDesc != m_pImDesc) ) {
m_pImDesc = thisImDesc;
m_pContext->IASetInputLayout(m_pImDesc->pInputLayout);
m_pContext->IASetPrimitiveTopology(m_pImDesc->Topology);
m_pContext->VSSetShader(m_pImDesc->pSolidColorVS,0,0);
m_pContext->PSSetShader(m_pImDesc->pSolidColorPS,0,0);
m_pContext->PSSetSamplers(0,1,&m_pImDesc->pSampler);
m_pContext->OMSetBlendState(m_pImDesc->pBlendState,NULL,0xFFFFFFFF);
}
UINT stride = m_pImDesc->VertexSize;
UINT offset = 0;
ID3D11Buffer* pVBuffer = pImage->GetpVertexBuffer();
ID3D11ShaderResourceView* pColorMap = pImage->GetpColorMap();
m_pContext->IASetVertexBuffers(0,1,&pVBuffer,&stride,&offset);
m_pContext->PSSetShaderResources(0,1,&pColorMap);
//set constant buffers?
m_pContext->Draw(6,0);
}
Yes, as long as your texture coordinates are hardcoded to 0.0 through 1.0 in your vertex buffer, you can use a texture transformation matrix. It's a 3x3 matrix that will transform your 2D texture coordinates.
For instance, if you want to use the bottom-right quadrant of your texture (assuming top-left is origin), you could use the following matrix:
0.5 0.0 0.0
0.0 0.5 0.0
0.5 0.5 1.0
Then, in the vertex shader, you multiply the texture coordinates by that matrix like so:
float3 coord = float3(In.texCoord, 1.0);
coord *= textureTransform;
Out.texCoord = coord.xy / coord.z;
In.texCoord and Out.texCoord being float2 input and output texture coordinates respectively.
The division by Z is optional if you are only doing affine transformations (translations, scaling, rotations and skews) so feel free to remove it if not needed.
To generalize the matrix:
Sx 0.0 0.0
0.0 Sy 0.0
Tx Ty 1.0
Where Txy is the position of the clip area and Sxy the size of the clip area, in texture coordinates.
This is a simple program that draws a 3d cube with a texture. The problem is I can not see the texture because the lights are not working.I have turned off the lights just to make sure the texture is there and it is.So if any one can help me figure out why the lights are not working I would greatly appreciate it.
#include "DirectXGame.h"
DirectXGame::DirectXGame(void)
{
//init to zero good pratice
m_pD3DObject=0;
m_pD3DDevice=0;
m_currTime=0;
m_prevTime=0;
ZeroMemory(&m_D3Dpp,sizeof(m_D3Dpp));
FOV=D3DXToRadian(65.0f);
aspectRatio=800/600;
nearPlane=1.0f;
farPlane=1000.0f;
}
DirectXGame::~DirectXGame(void)
{
}
//create class for input
DirectXInput DXClass;
void DirectXGame::Initialize(HWND hWnd ,HINSTANCE hInst,bool bWindowed) // create the material struct)//
{
// grab the window width and height fronm the HWND
RECT r;
GetWindowRect(hWnd, &r);
m_nWidth = r.right - r.left;
m_nHeight = r.bottom - r.top;
m_bVSync = false;
// Create the D3D Object
m_pD3DObject = Direct3DCreate9(D3D_SDK_VERSION);
// Create our presentation parameters for our D3D Device
m_D3Dpp.hDeviceWindow = hWnd; // Handle to the window
m_D3Dpp.Windowed = bWindowed; // Windowed or Full-screen?
m_D3Dpp.BackBufferCount = 1; // Number of back-buffers
m_D3Dpp.BackBufferFormat = D3DFMT_X8R8G8B8; // Back-buffer pixel format
m_D3Dpp.BackBufferWidth = m_nWidth; // Back-buffer width
m_D3Dpp.BackBufferHeight = m_nHeight; // Back-buffer height
m_D3Dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // Swap effectm_bVSync ? D3DPRESENT_INTERVAL_DEFAULT :
m_D3Dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
m_D3Dpp.FullScreen_RefreshRateInHz = bWindowed ? 0 : D3DPRESENT_RATE_DEFAULT;
m_D3Dpp.EnableAutoDepthStencil = TRUE; // Enable depth and stencil buffer
m_D3Dpp.AutoDepthStencilFormat = D3DFMT_D24S8; // Depth/Stencil buffer bit format
m_D3Dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL; // Discard the depth/stencil buffer upon Present()
m_D3Dpp.MultiSampleQuality = 0; // MSAA quality
m_D3Dpp.MultiSampleType = D3DMULTISAMPLE_NONE; // MSAA type
// Check the device's capabilities
DWORD deviceBehaviorFlags = 0;
m_pD3DObject->GetDeviceCaps(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, &m_D3DCaps);
// Determine vertex processing mode
if(m_D3DCaps.DevCaps & D3DCREATE_HARDWARE_VERTEXPROCESSING)
{
deviceBehaviorFlags |= D3DCREATE_HARDWARE_VERTEXPROCESSING;
}
else
{
deviceBehaviorFlags |= D3DCREATE_SOFTWARE_VERTEXPROCESSING;
}
// if hardware vertex processing is on, check for pure
if(m_D3DCaps.DevCaps & D3DCREATE_PUREDEVICE && deviceBehaviorFlags & D3DCREATE_HARDWARE_VERTEXPROCESSING)
{
deviceBehaviorFlags |= D3DCREATE_PUREDEVICE;
}
// Create D3D Device
m_pD3DObject->CreateDevice(
D3DADAPTER_DEFAULT, // Default display adapter
D3DDEVTYPE_HAL, // Device type to use
hWnd, // Handle to our window
deviceBehaviorFlags, // D3DCREATE_HARDWARE_VERTEXPROCESSINGVertex Processing Behavior Flags (PUREDEVICE, HARDWARE_VERTEXPROCESSING, SOFTWARE_VERTEXPROCESSING)
&m_D3Dpp, // Presentation parameters
&m_pD3DDevice); // Return a created D3D Device
//=================================================================//
// Create/Load Sprite & Font D3D and COM objects
//Create font
D3DXCreateFont(m_pD3DDevice, 23, 0, FW_BOLD, 0, true,
DEFAULT_CHARSET, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY,
DEFAULT_PITCH | FF_DONTCARE, TEXT("Times New Roman"),
&m_pD3DFont);
//for font 1 "Name"
RECT rct;
rct.left=2;
rct.right=780;
rct.top=10;
rct.bottom=rct.top+20;
//MATRIX
eyePos.x = 0;
eyePos.y = 2;
eyePos.z = -10;
lookAt.x = 0;
lookAt.y = 0;
lookAt.z = 0;
upVec.x = 0;
upVec.y = 1;
upVec.z = 0;
D3DXMatrixLookAtLH( &view_Matrix, &eyePos, &lookAt, &upVec);
m_pD3DDevice->SetTransform( D3DTS_VIEW, &view_Matrix);
// projection matrix
D3DXMatrixPerspectiveFovLH( &pro_Matrix, FOV, aspectRatio, nearPlane, farPlane);
m_pD3DDevice->SetTransform( D3DTS_PROJECTION, &pro_Matrix);
// MATRIX: VertexElement Declaration
D3DVERTEXELEMENT9 declaration[] =
{
{0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
{0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0},
{0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
D3DDECL_END()
};
//LPDIRECT3DVERTEXDECLARATION9 m_pVtxDeclObject;
// Create vertex declaration
m_pD3DDevice->CreateVertexDeclaration(declaration,&vertDec);
///---CUBE: Vertex and Indicies :START---///
// Load vertex info, listed per cube face quads
// Front
m_cubeVerts[0].position = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
m_cubeVerts[1].position = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
m_cubeVerts[2].position = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
m_cubeVerts[3].position = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
D3DXVec3Normalize(&m_cubeVerts[0].normal, &D3DXVECTOR3(0.0f, 0.0f, -1.0f));
D3DXVec3Normalize(&m_cubeVerts[1].normal, &D3DXVECTOR3(0.0f, 0.0f, -1.0f));
D3DXVec3Normalize(&m_cubeVerts[2].normal, &D3DXVECTOR3(0.0f, 0.0f, -1.0f));
D3DXVec3Normalize(&m_cubeVerts[3].normal, &D3DXVECTOR3(0.0f, 0.0f, -1.0f));
m_cubeVerts[0].uv = D3DXVECTOR2(0.0f, 1.0f);
m_cubeVerts[1].uv = D3DXVECTOR2(0.0f, 0.0f);
m_cubeVerts[2].uv = D3DXVECTOR2(1.0f, 0.0f);
m_cubeVerts[3].uv = D3DXVECTOR2(1.0f, 1.0f);
// Back
m_cubeVerts[4].position = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
m_cubeVerts[5].position = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
m_cubeVerts[6].position = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
m_cubeVerts[7].position = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
D3DXVec3Normalize(&m_cubeVerts[4].normal, &D3DXVECTOR3(0.0f, 0.0f, 1.0f));
D3DXVec3Normalize(&m_cubeVerts[5].normal, &D3DXVECTOR3(0.0f, 0.0f, 1.0f));
D3DXVec3Normalize(&m_cubeVerts[6].normal, &D3DXVECTOR3(0.0f, 0.0f, 1.0f));
D3DXVec3Normalize(&m_cubeVerts[7].normal, &D3DXVECTOR3(0.0f, 0.0f, 1.0f));
m_cubeVerts[4].uv = D3DXVECTOR2(1.0f, 1.0f);
m_cubeVerts[5].uv = D3DXVECTOR2(0.0f, 1.0f);
m_cubeVerts[6].uv = D3DXVECTOR2(0.0f, 0.0f);
m_cubeVerts[7].uv = D3DXVECTOR2(1.0f, 0.0f);
// Top
m_cubeVerts[8].position = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
m_cubeVerts[9].position = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
m_cubeVerts[10].position = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
m_cubeVerts[11].position = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
D3DXVec3Normalize(&m_cubeVerts[8].normal, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[9].normal, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[10].normal, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[11].normal, &D3DXVECTOR3(0.0f, 1.0f, 0.0f));
m_cubeVerts[8].uv = D3DXVECTOR2(0.0f, 1.0f);
m_cubeVerts[9].uv = D3DXVECTOR2(0.0f, 0.0f);
m_cubeVerts[10].uv = D3DXVECTOR2(1.0f, 0.0f);
m_cubeVerts[11].uv = D3DXVECTOR2(1.0f, 1.0f);
// Bottom
m_cubeVerts[12].position = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
m_cubeVerts[13].position = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
m_cubeVerts[14].position = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
m_cubeVerts[15].position = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
D3DXVec3Normalize(&m_cubeVerts[12].normal, &D3DXVECTOR3(0.0f, -1.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[13].normal, &D3DXVECTOR3(0.0f, -1.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[14].normal, &D3DXVECTOR3(0.0f, -1.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[15].normal, &D3DXVECTOR3(0.0f, -1.0f, 0.0f));
m_cubeVerts[12].uv = D3DXVECTOR2(1.0f, 1.0f);
m_cubeVerts[13].uv = D3DXVECTOR2(0.0f, 1.0f);
m_cubeVerts[14].uv = D3DXVECTOR2(0.0f, 0.0f);
m_cubeVerts[15].uv = D3DXVECTOR2(1.0f, 0.0f);
// Left
m_cubeVerts[16].position = D3DXVECTOR3(-1.0f, -1.0f, 1.0f);
m_cubeVerts[17].position = D3DXVECTOR3(-1.0f, 1.0f, 1.0f);
m_cubeVerts[18].position = D3DXVECTOR3(-1.0f, 1.0f, -1.0f);
m_cubeVerts[19].position = D3DXVECTOR3(-1.0f, -1.0f, -1.0f);
D3DXVec3Normalize(&m_cubeVerts[16].normal, &D3DXVECTOR3(-1.0f, 0.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[17].normal, &D3DXVECTOR3(-1.0f, 0.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[18].normal, &D3DXVECTOR3(-1.0f, 0.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[19].normal, &D3DXVECTOR3(-1.0f, 0.0f, 0.0f));
m_cubeVerts[16].uv = D3DXVECTOR2(0.0f, 1.0f);
m_cubeVerts[17].uv = D3DXVECTOR2(0.0f, 0.0f);
m_cubeVerts[18].uv = D3DXVECTOR2(1.0f, 0.0f);
m_cubeVerts[19].uv = D3DXVECTOR2(1.0f, 1.0f);
// Right
m_cubeVerts[20].position = D3DXVECTOR3(1.0f, -1.0f, -1.0f);
m_cubeVerts[21].position = D3DXVECTOR3(1.0f, 1.0f, -1.0f);
m_cubeVerts[22].position = D3DXVECTOR3(1.0f, 1.0f, 1.0f);
m_cubeVerts[23].position = D3DXVECTOR3(1.0f, -1.0f, 1.0f);
D3DXVec3Normalize(&m_cubeVerts[20].normal, &D3DXVECTOR3(1.0f, 0.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[21].normal, &D3DXVECTOR3(1.0f, 0.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[22].normal, &D3DXVECTOR3(1.0f, 0.0f, 0.0f));
D3DXVec3Normalize(&m_cubeVerts[23].normal, &D3DXVECTOR3(1.0f, 0.0f, 0.0f));
m_cubeVerts[20].uv = D3DXVECTOR2(0.0f, 1.0f);
m_cubeVerts[21].uv = D3DXVECTOR2(0.0f, 0.0f);
m_cubeVerts[22].uv = D3DXVECTOR2(1.0f, 0.0f);
m_cubeVerts[23].uv = D3DXVECTOR2(1.0f, 1.0f);
// Load index info, refers into index into verts array to compose triangles
// Note: A clockwise winding order of verts will show the front face.
// Front
m_cubeIndices[0] = 0; m_cubeIndices[1] = 1; m_cubeIndices[2] = 2; // Triangle 0
m_cubeIndices[3] = 0; m_cubeIndices[4] = 2; m_cubeIndices[5] = 3; // Triangle 1
// Back
m_cubeIndices[6] = 4; m_cubeIndices[7] = 5; m_cubeIndices[8] = 6; // Triangle 2
m_cubeIndices[9] = 4; m_cubeIndices[10] = 6; m_cubeIndices[11] = 7; // Triangle 3
// Top
m_cubeIndices[12] = 8; m_cubeIndices[13] = 9; m_cubeIndices[14] = 10; // Triangle 4
m_cubeIndices[15] = 8; m_cubeIndices[16] = 10; m_cubeIndices[17] = 11; // Triangle 5
// Bottom
m_cubeIndices[18] = 12; m_cubeIndices[19] = 13; m_cubeIndices[20] = 14; // Triangle 6
m_cubeIndices[21] = 12; m_cubeIndices[22] = 14; m_cubeIndices[23] = 15; // Triangle 7
// Left
m_cubeIndices[24] = 16; m_cubeIndices[25] = 17; m_cubeIndices[26] = 18; // Triangle 8
m_cubeIndices[27] = 16; m_cubeIndices[28] = 18; m_cubeIndices[29] = 19; // Triangle 9
// Right
m_cubeIndices[30] = 20; m_cubeIndices[31] = 21; m_cubeIndices[32] = 22; // Triangle 10
m_cubeIndices[33] = 20; m_cubeIndices[34] = 22; m_cubeIndices[35] = 23; // Triangle 11
///---CUBE: Vertex and Indicies :END---///
//create buffers
// create a vertex buffer interface called i_buffer
m_pD3DDevice->CreateVertexBuffer(4*6*sizeof(Vertex),
D3DUSAGE_WRITEONLY,
0,
D3DPOOL_MANAGED,
&VB,
NULL);
void* pVertices;
// lock VB and load the vertices into it
VB->Lock(0, 0,&pVertices, 0);
// send array
memcpy(pVertices, m_cubeVerts, 4*6*sizeof(Vertex));
//unlock
VB->Unlock();
///////////////////////////////////////////////////
m_pD3DDevice->CreateIndexBuffer(3*12*sizeof(WORD), // 3 and 12
D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16,
D3DPOOL_MANAGED,
&IB,
NULL);
void* pIndices;
// lock index
IB->Lock(0,0,&pIndices,0);
//send array of indices to vram
memcpy(pIndices, m_cubeIndices, 3*12*sizeof(WORD));
//unlock index
IB->Unlock();
D3DLIGHT9 light;
D3DMATERIAL9 m_Mat;
ZeroMemory(&light, sizeof(light));
// clear out the light struct for use
light.Type = D3DLIGHT_POINT;
// make the light type 'directional light'
light.Diffuse.r = 0.5f;
light.Diffuse.g = 0.5f;
light.Diffuse.b = 0.5f;
light.Diffuse.a = 1.0f;
light.Ambient.r = 0.2f;
light.Ambient.g = 0.2f;
light.Ambient.b = 1.0f;
light.Specular.r = 1.0f;
light.Specular.g = 1.0f;
light.Specular.b = 1.0f;
// set the lighting position
light.Position.x = 30;
light.Position.y = 10;
light.Position.z = -10;
light.Range = 900.0f;
light.Attenuation0 = 0.0f;
light.Attenuation1 = 0.125f;
light.Attenuation2 = 0.0f;
m_pD3DDevice->SetLight(0, &light);
// send the light struct properties to light #0
m_pD3DDevice->LightEnable(0, TRUE);
// turn on light #0
ZeroMemory(&m_Mat, sizeof(m_Mat));
// clear out the struct for use
m_Mat.Diffuse.r = 1.0f;
m_Mat.Diffuse.g = 0.0f;
m_Mat.Diffuse.b = 0.0f;
m_Mat.Diffuse.a = 0.0f;
// set diffuse color to white
m_Mat.Ambient.r = 0.2f;
m_Mat.Ambient.g = 0.2f;
m_Mat.Ambient.b = 0.2f;
m_Mat.Ambient.a = 1.0f;
// set ambient color to white
m_Mat.Specular.r = 1.0f;
m_Mat.Specular.g =1.0f;
m_Mat.Specular.b =1.0f;
m_Mat.Specular.a =1.0f;
m_Mat.Power = 100.0f;
m_pD3DDevice->SetMaterial(&m_Mat);
// Create a texture using the with "test.tga" from the sprite labs.
//Apply tri-linear filtering to the texture, by modifying the sampler states by calling the device's SetSamplerState().
D3DXCreateTextureFromFile(m_pD3DDevice, L"test.png",&m_Texture);
//Apply tri-linear filtering to the texture, by modifying the sampler states by calling the device's SetSamplerState().
m_pD3DDevice->SetSamplerState( 0,D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
m_pD3DDevice->SetSamplerState( 0,D3DSAMP_MIPFILTER, D3DTEXF_LINEAR);
m_pD3DDevice->SetSamplerState( 0,D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
}
void DirectXGame::Update(HWND hWnd, bool& bWindowed, double dt)
{
}
void DirectXGame::Render()
{
// if our d3d device was not craeted return
if(!m_pD3DDevice)
return;
m_pD3DDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(100,149,237), 1, 0); // 100,149,237 00255
// Begin the scene
if( SUCCEEDED( m_pD3DDevice->BeginScene() ) )
{
m_pD3DDevice->SetVertexDeclaration( vertDec);
//set cube postion
D3DXMATRIX translation, rotation, scale, world, position;
float index = 0.0f; index+=0.05f;
D3DXMatrixTranslation(&translation,0,0,0);
D3DXMatrixRotationY(&rotation, timeGetTime()/1000);
D3DXMatrixScaling(&scale,1,1, 1.0f);
world = scale*rotation*translation;
m_pD3DDevice->SetTransform(D3DTS_WORLD, &world);
// select the vertex and index buffers to use
m_pD3DDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_TRUE);
m_pD3DDevice->SetRenderState( D3DRS_SPECULARENABLE, TRUE );
m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, D3DCOLOR_XRGB(60,60,60));
m_pD3DDevice->SetStreamSource(0, VB, 0, sizeof(Vertex));
m_pD3DDevice->SetIndices(IB);
m_pD3DDevice->SetMaterial(&m_Mat);
m_pD3DDevice->SetTexture( 0,m_Texture);
m_pD3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,//D3DPRIMITIVETYPE Type
0,/*BaseVertexIndex*/
0, //* MinIndex*/
24, /*NumVertices*/
0, /*StartIndex*/
12);//PrimitiveCount
///////////////////////////////////////////////////////////////////////////
//Font 1 "Name"
RECT rct;
rct.bottom = m_nHeight;
rct.top=2;
rct.left=658;
rct.right=m_nWidth;
//for the font2 FPS
RECT rect;
rect.bottom = m_nHeight;
rect.top =2;
rect.left = 10;
rect.right = m_nWidth;
wchar_t buffer[64];
swprintf_s(buffer, 64,L"Frames Per Second: %d", m_FPS);
m_pD3DFont->DrawText(0, buffer, -1, &rect, DT_TOP | DT_NOCLIP, D3DCOLOR_ARGB(255,255,255,255));
// Create a colour for the text ( blue)
D3DCOLOR fontColor = D3DCOLOR_ARGB(255,0,0,255);
//draw the text
m_pD3DFont->DrawText(NULL, L"Mariana Serrato", -1, &rct, 0, fontColor ); // move test to far right
// End the scene
m_pD3DDevice->EndScene();
// present the back buffer to the screen
m_pD3DDevice->Present(NULL, NULL, NULL, NULL);
//calculate Frames Per Second
m_currTime = timeGetTime();
static int fspCounter = 0;
if(m_currTime - m_prevTime >= 1000.0f)
{
m_prevTime = m_currTime;
m_FPS = fspCounter;
fspCounter =0;
} else {
++fspCounter;
}
}
}
void DirectXGame::Shutdown()
{
SAFE_RELEASE(VB);
SAFE_RELEASE(IB);
SAFE_RELEASE(vertDec);
SAFE_RELEASE(m_pD3DFont);
SAFE_RELEASE(m_Texture);
SAFE_RELEASE(m_Sprite);
SAFE_RELEASE(m_pD3DDevice);
SAFE_RELEASE(m_pD3DObject);
}
//////////////////////////////////////////////////////////////////////////////////////////
.h header file
pragma once
include // for random nums
include
include
include
include
include
include "DirectXInput.h"
include
include
pragma comment (lib, "d3d9.lib")
pragma comment (lib, "d3dx9.lib")
pragma comment(lib, "winmm.lib")//for timeGetTime()
pragma comment(lib, "dinput8.lib")
pragma comment(lib, "dxguid.lib")
// Macro to Safely release com obejcts
define SAFE_RELEASE(x) if(x) {x->Release(); x = 0;}
// Direct Input version
define DIRECTINPUT_VERSION 0x0800
// Define window size
define SCREEN_WIDTH 800
define SCREEN_HEIGHT 600
//#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)
class DirectXGame
{
struct Vertex
{
D3DXVECTOR3 position;
D3DXVECTOR3 normal;
D3DXVECTOR2 uv;
};
IDirect3D9* m_pD3DObject;
IDirect3DDevice9* m_pD3DDevice;
D3DPRESENT_PARAMETERS m_D3Dpp;
ID3DXFont* m_pD3DFont; //Font
LPDIRECT3DTEXTURE9 m_Texture;
ID3DXSprite* m_Sprite;//Sprite
D3DXVECTOR3 texCenter,eyePos,lookAt,upVec;
D3DCAPS9 m_D3DCaps; //D3D Device Caps
D3DLIGHT9 m_Light;
D3DMATERIAL9 m_Mat;
D3DVERTEXELEMENT9 m_Element;
D3DXMATRIX view_Matrix, pro_Matrix;
// cube
Vertex m_cubeVerts[24];
WORD m_cubeIndices[36];
IDirect3DVertexBuffer9* VB;
IDirect3DIndexBuffer9* IB;
IDirect3DVertexDeclaration9* vertDec;
bool m_bVSync;
char buffer [256];
int m_nWidth, m_nHeight;
int m_FPS,alfa[5],mFPS,mMilliSecPerFrame;
float m_currTime,m_prevTime,FOV, aspectRatio, nearPlane, farPlane;
DWORD D3DUSASE_DYNAMIC,D3DUSASE_WRITEONLY;
public:
DirectXGame(void);
~DirectXGame(void);
void Initialize(HWND hWnd,HINSTANCE hInst, bool bWindowed);
bool isDeviceLost();
void Update(HWND hWnd, bool& bWindowed, double dt);
void Render();
void CheckPosition();
void Shutdown();
};
You haven't enabled D3DRS_LIGHTING.
m_pD3DDevice->setRenderState(D3DRS_LIGHTING, TRUE);
So I have begun learning OpenGL, reading from the book "OpenGL Super Bible 5 ed.". It's explains things really well, and I have been able to create my first gl program myself! Just something simple, a rotating 3d pyramid.
Now for some reason one of the faces are not rendering. I checked the vertecies (plotted it on paper first) and it seemed to be right. Found out if I changed the shader to draw a line loop, it would render. However it would not render a triangle. Can anyone explain why?
void setupRC()
{
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
shaderManager.InitializeStockShaders();
M3DVector3f vVerts1[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
M3DVector3f vVerts2[] = {-0.5f,0.0f,-0.5f,0.0f,0.5f,0.0f,-0.5f,0.0f,0.5f};
M3DVector3f vVerts3[] = {-0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f};
M3DVector3f vVerts4[] = {0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,0.5f,0.0f,-0.5f};
triangleBatch1.Begin(GL_LINE_LOOP, 3);
triangleBatch1.CopyVertexData3f(vVerts1);
triangleBatch1.End();
triangleBatch2.Begin(GL_TRIANGLES, 3);
triangleBatch2.CopyVertexData3f(vVerts2);
triangleBatch2.End();
triangleBatch3.Begin(GL_TRIANGLES, 3);
triangleBatch3.CopyVertexData3f(vVerts3);
triangleBatch3.End();
triangleBatch4.Begin(GL_TRIANGLES, 3);
triangleBatch4.CopyVertexData3f(vVerts4);
triangleBatch4.End();
glEnable(GL_CULL_FACE);
}
float rot = 1;
void renderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
GLfloat vRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
GLfloat vBlue[] = {0.0f, 1.0f, 0.0f, 0.5f};
GLfloat vGreen[] = {0.0f, 0.0f, 1.0f, 0.5f};
GLfloat vWhite[] = {1.0f, 1.0f, 1.0f, 0.5f};
M3DMatrix44f transformMatrix;
if (rot >= 360)
rot = 0;
else
rot = rot + 1;
m3dRotationMatrix44(transformMatrix,m3dDegToRad(rot),0.0f,1.0f,0.0f);
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vRed);
triangleBatch1.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vBlue);
triangleBatch2.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vGreen);
triangleBatch3.Draw();
shaderManager.UseStockShader(GLT_SHADER_FLAT, transformMatrix, vWhite);
triangleBatch4.Draw();
glutSwapBuffers();
glutPostRedisplay();
Sleep(10);
}
You've most likely defined the vertices in clockwise order for the triangle that isn't showing, and in counterclockwise order (normally the default) for those that are. Clockwise winding essentially creates an inward facing normal and thus OpenGL won't bother to render it when culling is enabled.
The easiest way to check this is to set glCullFace(GL_FRONT)--that should toggle it so you see the missing triangle and no longer see the other three.
The only thing I see that affects polygons here is glEnable(GL_CULL_FACE);.
You shouldn't have that, because if you plot your vertices backwards, the polygon won't render.
Remove it or actually call glDisable(GL_CULL_FACE); to be sure.
In your case, it's not likely that you want to draw a polygon that you can see from one side only.