将值传递给着色器时出现问题
我在将值传递给着色器时遇到问题。我的应用程序编译良好,但我的立方体对象不会着色。以下是我的大部分代码。
我与着色器通信的大部分代码都在 createObject 方法
myGame.cpp
#include "MyGame.h"
#include "OneColorCube.h"
/* This code sets a projection and shows a turning cube. What has been added is the project, rotation and
a rasterizer to change the rasterization of the cube. The issue that was going on was something with the effect file
which was causing the vertices not to be rendered correctly.*/
typedef struct
{
ID3D10Effect* pEffect;
ID3D10EffectTechnique* pTechnique;
//vertex information
ID3D10Buffer* pVertexBuffer;
ID3D10Buffer* pIndicesBuffer;
ID3D10InputLayout* pVertexLayout;
UINT numVertices;
UINT numIndices;
}ModelObject;
ModelObject modelObject;
// World Matrix
D3DXMATRIX WorldMatrix;
// View Matrix
D3DXMATRIX ViewMatrix;
// Projection Matrix
D3DXMATRIX ProjectionMatrix;
ID3D10EffectMatrixVariable* pProjectionMatrixVariable = NULL;
ID3D10EffectVectorVariable* pLightVarible = NULL;
bool MyGame::InitDirect3D()
{
if(!DX3dApp::InitDirect3D())
{
return false;
}
D3D10_RASTERIZER_DESC rastDesc;
rastDesc.FillMode = D3D10_FILL_WIREFRAME;
rastDesc.CullMode = D3D10_CULL_FRONT;
rastDesc.FrontCounterClockwise = true;
rastDesc.DepthBias = false;
rastDesc.DepthBiasClamp = 0;
rastDesc.SlopeScaledDepthBias = 0;
rastDesc.DepthClipEnable = false;
rastDesc.ScissorEnable = false;
rastDesc.MultisampleEnable = false;
rastDesc.AntialiasedLineEnable = false;
ID3D10RasterizerState *g_pRasterizerState;
mpD3DDevice->CreateRasterizerState(&rastDesc, &g_pRasterizerState);
//mpD3DDevice->RSSetState(g_pRasterizerState);
// Set up the World Matrix
D3DXMatrixIdentity(&WorldMatrix);
D3DXMatrixLookAtLH(&ViewMatrix, new D3DXVECTOR3(0.0f, 10.0f, -20.0f), new D3DXVECTOR3(0.0f, 0.0f, 0.0f), new D3DXVECTOR3(0.0f, 1.0f, 0.0f));
// Set up the projection matrix
D3DXMatrixPerspectiveFovLH(&ProjectionMatrix, (float)D3DX_PI * 0.5f, (float)mWidth/(float)mHeight, 0.1f, 100.0f);
if(!CreateObject())
{
return false;
}
return true;
}
//These are actions that take place after the clearing of the buffer and before the present
void MyGame::GameDraw()
{
static float rotationAngleY = 15.0f;
static float rotationAngleX = 0.0f;
static D3DXMATRIX rotationXMatrix;
static D3DXMATRIX rotationYMatrix;
// create the rotation matrix using the rotation angle
D3DXMatrixRotationY(&rotationYMatrix, rotationAngleY);
D3DXMatrixRotationX(&rotationXMatrix, rotationAngleX);
//rotationAngleY += (float)D3DX_PI * 0.002f;
//rotationAngleX += (float)D3DX_PI * 0.001f;
WorldMatrix = rotationYMatrix * rotationXMatrix;
// Set the input layout
mpD3DDevice->IASetInputLayout(modelObject.pVertexLayout);
// Set vertex buffer
UINT stride = sizeof(VertexPos);
UINT offset = 0;
mpD3DDevice->IASetVertexBuffers(0, 1, &modelObject.pVertexBuffer, &stride, &offset);
// Set primitive topology
mpD3DDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
//ViewMatrix._43 += 0.005f;
// Combine and send the final matrix to the shader
D3DXMATRIX finalMatrix = (WorldMatrix * ViewMatrix * ProjectionMatrix);
pProjectionMatrixVariable->SetMatrix((float*)&finalMatrix);
// make sure modelObject is valid
// Render a model object
D3D10_TECHNIQUE_DESC techniqueDescription;
modelObject.pTechnique->GetDesc(&techniqueDescription);
// Loop through the technique passes
for(UINT p=0; p < techniqueDescription.Passes; ++p)
{
modelObject.pTechnique->GetPassByIndex(p)->Apply(0);
// draw the cube using all 36 vertices and 12 triangles
mpD3DDevice->Draw(36,0);
}
}
//Render actually incapsulates Gamedraw, so you can call data before you actually clear the buffer or after you
//present data
void MyGame::Render()
{
DX3dApp::Render();
}
bool MyGame::CreateObject()
{
//Create Layout
D3D10_INPUT_ELEMENT_DESC layout[] = {
{"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_R32G32B32A32_FLOAT, 0 , 24, D3D10_INPUT_PER_VERTEX_DATA, 0}
};
UINT numElements = (sizeof(layout)/sizeof(layout[0]));
modelObject.numVertices = sizeof(vertices)/sizeof(VertexPos);
for(int i = 0; i < modelObject.numVertices; i += 3)
{
D3DXVECTOR3 out;
D3DXVECTOR3 v1 = vertices[0 + i].pos;
D3DXVECTOR3 v2 = vertices[1 + i].pos;
D3DXVECTOR3 v3 = vertices[2 + i].pos;
D3DXVECTOR3 u = v2 - v1;
D3DXVECTOR3 v = v3 - v1;
D3DXVec3Cross(&out, &u, &v);
D3DXVec3Normalize(&out, &out);
vertices[0 + i].normal = out;
vertices[1 + i].normal = out;
vertices[2 + i].normal = out;
}
//Create buffer desc
D3D10_BUFFER_DESC bufferDesc;
bufferDesc.Usage = D3D10_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(VertexPos) * modelObject.numVertices;
bufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA initData;
initData.pSysMem = vertices;
//Create the buffer
HRESULT hr = mpD3DDevice->CreateBuffer(&bufferDesc, &initData, &modelObject.pVertexBuffer);
if(FAILED(hr))
return false;
/*
//Create indices
DWORD indices[] =
{
0,1,3,
1,2,3
};
ModelObject.numIndices = sizeof(indices)/sizeof(DWORD);
bufferDesc.ByteWidth = sizeof(DWORD) * ModelObject.numIndices;
bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;
initData.pSysMem = indices;
hr = mpD3DDevice->CreateBuffer(&bufferDesc, &initData, &ModelObject.pIndicesBuffer);
if(FAILED(hr))
return false;*/
/////////////////////////////////////////////////////////////////////////////
//Set up fx files
LPCWSTR effectFilename = L"effect.fx";
modelObject.pEffect = NULL;
hr = D3DX10CreateEffectFromFile(effectFilename,
NULL,
NULL,
"fx_4_0",
D3D10_SHADER_ENABLE_STRICTNESS,
0,
mpD3DDevice,
NULL,
NULL,
&modelObject.pEffect,
NULL,
NULL);
if(FAILED(hr))
return false;
pProjectionMatrixVariable = modelObject.pEffect->GetVariableByName("Projection")->AsMatrix();
pLightVarible = modelObject.pEffect->GetVariableByName("lightSource")->AsVector();
//Dont sweat the technique. Get it!
LPCSTR effectTechniqueName = "Render";
D3DXVECTOR3 vLight(10.0f, 10.0f, 10.0f);
pLightVarible->SetFloatVector(vLight);
modelObject.pTechnique = modelObject.pEffect->GetTechniqueByName(effectTechniqueName);
if(modelObject.pTechnique == NULL)
return false;
//Create Vertex layout
D3D10_PASS_DESC passDesc;
modelObject.pTechnique->GetPassByIndex(0)->GetDesc(&passDesc);
hr = mpD3DDevice->CreateInputLayout(layout, numElements,
passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize,
&modelObject.pVertexLayout);
if(FAILED(hr))
return false;
return true;
}
中,下面是我的着色器
effect.fx
matrix Projection;
float3 lightSource;
float4 lightColor = {0.5, 0.5, 0.5, 0.5};
// PS_INPUT - input variables to the pixel shader
// This struct is created and fill in by the
// vertex shader
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
float4 Normal : NORMAL;
};
////////////////////////////////////////////////
// Vertex Shader - Main Function
///////////////////////////////////////////////
PS_INPUT VS(float4 Pos : POSITION, float4 Color : COLOR, float4 Normal : NORMAL)
{
PS_INPUT psInput;
// Pass through both the position and the color
psInput.Pos = mul( Pos, Projection );
psInput.Color = Color;
psInput.Normal = Normal;
return psInput;
}
///////////////////////////////////////////////
// Pixel Shader
///////////////////////////////////////////////
float4 PS(PS_INPUT psInput) : SV_Target
{
float4 finalColor = 0;
finalColor = saturate(dot(lightSource, psInput.Normal) * lightColor);
return finalColor;
}
// Define the technique
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}
I am having issues passing values to my shader. My application compiles fine, but my cube object won't shade. Below is majority of my code.
Most of my code for communicating with my shader is in createObject method
myGame.cpp
#include "MyGame.h"
#include "OneColorCube.h"
/* This code sets a projection and shows a turning cube. What has been added is the project, rotation and
a rasterizer to change the rasterization of the cube. The issue that was going on was something with the effect file
which was causing the vertices not to be rendered correctly.*/
typedef struct
{
ID3D10Effect* pEffect;
ID3D10EffectTechnique* pTechnique;
//vertex information
ID3D10Buffer* pVertexBuffer;
ID3D10Buffer* pIndicesBuffer;
ID3D10InputLayout* pVertexLayout;
UINT numVertices;
UINT numIndices;
}ModelObject;
ModelObject modelObject;
// World Matrix
D3DXMATRIX WorldMatrix;
// View Matrix
D3DXMATRIX ViewMatrix;
// Projection Matrix
D3DXMATRIX ProjectionMatrix;
ID3D10EffectMatrixVariable* pProjectionMatrixVariable = NULL;
ID3D10EffectVectorVariable* pLightVarible = NULL;
bool MyGame::InitDirect3D()
{
if(!DX3dApp::InitDirect3D())
{
return false;
}
D3D10_RASTERIZER_DESC rastDesc;
rastDesc.FillMode = D3D10_FILL_WIREFRAME;
rastDesc.CullMode = D3D10_CULL_FRONT;
rastDesc.FrontCounterClockwise = true;
rastDesc.DepthBias = false;
rastDesc.DepthBiasClamp = 0;
rastDesc.SlopeScaledDepthBias = 0;
rastDesc.DepthClipEnable = false;
rastDesc.ScissorEnable = false;
rastDesc.MultisampleEnable = false;
rastDesc.AntialiasedLineEnable = false;
ID3D10RasterizerState *g_pRasterizerState;
mpD3DDevice->CreateRasterizerState(&rastDesc, &g_pRasterizerState);
//mpD3DDevice->RSSetState(g_pRasterizerState);
// Set up the World Matrix
D3DXMatrixIdentity(&WorldMatrix);
D3DXMatrixLookAtLH(&ViewMatrix, new D3DXVECTOR3(0.0f, 10.0f, -20.0f), new D3DXVECTOR3(0.0f, 0.0f, 0.0f), new D3DXVECTOR3(0.0f, 1.0f, 0.0f));
// Set up the projection matrix
D3DXMatrixPerspectiveFovLH(&ProjectionMatrix, (float)D3DX_PI * 0.5f, (float)mWidth/(float)mHeight, 0.1f, 100.0f);
if(!CreateObject())
{
return false;
}
return true;
}
//These are actions that take place after the clearing of the buffer and before the present
void MyGame::GameDraw()
{
static float rotationAngleY = 15.0f;
static float rotationAngleX = 0.0f;
static D3DXMATRIX rotationXMatrix;
static D3DXMATRIX rotationYMatrix;
// create the rotation matrix using the rotation angle
D3DXMatrixRotationY(&rotationYMatrix, rotationAngleY);
D3DXMatrixRotationX(&rotationXMatrix, rotationAngleX);
//rotationAngleY += (float)D3DX_PI * 0.002f;
//rotationAngleX += (float)D3DX_PI * 0.001f;
WorldMatrix = rotationYMatrix * rotationXMatrix;
// Set the input layout
mpD3DDevice->IASetInputLayout(modelObject.pVertexLayout);
// Set vertex buffer
UINT stride = sizeof(VertexPos);
UINT offset = 0;
mpD3DDevice->IASetVertexBuffers(0, 1, &modelObject.pVertexBuffer, &stride, &offset);
// Set primitive topology
mpD3DDevice->IASetPrimitiveTopology(D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
//ViewMatrix._43 += 0.005f;
// Combine and send the final matrix to the shader
D3DXMATRIX finalMatrix = (WorldMatrix * ViewMatrix * ProjectionMatrix);
pProjectionMatrixVariable->SetMatrix((float*)&finalMatrix);
// make sure modelObject is valid
// Render a model object
D3D10_TECHNIQUE_DESC techniqueDescription;
modelObject.pTechnique->GetDesc(&techniqueDescription);
// Loop through the technique passes
for(UINT p=0; p < techniqueDescription.Passes; ++p)
{
modelObject.pTechnique->GetPassByIndex(p)->Apply(0);
// draw the cube using all 36 vertices and 12 triangles
mpD3DDevice->Draw(36,0);
}
}
//Render actually incapsulates Gamedraw, so you can call data before you actually clear the buffer or after you
//present data
void MyGame::Render()
{
DX3dApp::Render();
}
bool MyGame::CreateObject()
{
//Create Layout
D3D10_INPUT_ELEMENT_DESC layout[] = {
{"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_R32G32B32A32_FLOAT, 0 , 24, D3D10_INPUT_PER_VERTEX_DATA, 0}
};
UINT numElements = (sizeof(layout)/sizeof(layout[0]));
modelObject.numVertices = sizeof(vertices)/sizeof(VertexPos);
for(int i = 0; i < modelObject.numVertices; i += 3)
{
D3DXVECTOR3 out;
D3DXVECTOR3 v1 = vertices[0 + i].pos;
D3DXVECTOR3 v2 = vertices[1 + i].pos;
D3DXVECTOR3 v3 = vertices[2 + i].pos;
D3DXVECTOR3 u = v2 - v1;
D3DXVECTOR3 v = v3 - v1;
D3DXVec3Cross(&out, &u, &v);
D3DXVec3Normalize(&out, &out);
vertices[0 + i].normal = out;
vertices[1 + i].normal = out;
vertices[2 + i].normal = out;
}
//Create buffer desc
D3D10_BUFFER_DESC bufferDesc;
bufferDesc.Usage = D3D10_USAGE_DEFAULT;
bufferDesc.ByteWidth = sizeof(VertexPos) * modelObject.numVertices;
bufferDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA initData;
initData.pSysMem = vertices;
//Create the buffer
HRESULT hr = mpD3DDevice->CreateBuffer(&bufferDesc, &initData, &modelObject.pVertexBuffer);
if(FAILED(hr))
return false;
/*
//Create indices
DWORD indices[] =
{
0,1,3,
1,2,3
};
ModelObject.numIndices = sizeof(indices)/sizeof(DWORD);
bufferDesc.ByteWidth = sizeof(DWORD) * ModelObject.numIndices;
bufferDesc.BindFlags = D3D10_BIND_INDEX_BUFFER;
initData.pSysMem = indices;
hr = mpD3DDevice->CreateBuffer(&bufferDesc, &initData, &ModelObject.pIndicesBuffer);
if(FAILED(hr))
return false;*/
/////////////////////////////////////////////////////////////////////////////
//Set up fx files
LPCWSTR effectFilename = L"effect.fx";
modelObject.pEffect = NULL;
hr = D3DX10CreateEffectFromFile(effectFilename,
NULL,
NULL,
"fx_4_0",
D3D10_SHADER_ENABLE_STRICTNESS,
0,
mpD3DDevice,
NULL,
NULL,
&modelObject.pEffect,
NULL,
NULL);
if(FAILED(hr))
return false;
pProjectionMatrixVariable = modelObject.pEffect->GetVariableByName("Projection")->AsMatrix();
pLightVarible = modelObject.pEffect->GetVariableByName("lightSource")->AsVector();
//Dont sweat the technique. Get it!
LPCSTR effectTechniqueName = "Render";
D3DXVECTOR3 vLight(10.0f, 10.0f, 10.0f);
pLightVarible->SetFloatVector(vLight);
modelObject.pTechnique = modelObject.pEffect->GetTechniqueByName(effectTechniqueName);
if(modelObject.pTechnique == NULL)
return false;
//Create Vertex layout
D3D10_PASS_DESC passDesc;
modelObject.pTechnique->GetPassByIndex(0)->GetDesc(&passDesc);
hr = mpD3DDevice->CreateInputLayout(layout, numElements,
passDesc.pIAInputSignature,
passDesc.IAInputSignatureSize,
&modelObject.pVertexLayout);
if(FAILED(hr))
return false;
return true;
}
And below is my shader
effect.fx
matrix Projection;
float3 lightSource;
float4 lightColor = {0.5, 0.5, 0.5, 0.5};
// PS_INPUT - input variables to the pixel shader
// This struct is created and fill in by the
// vertex shader
struct PS_INPUT
{
float4 Pos : SV_POSITION;
float4 Color : COLOR0;
float4 Normal : NORMAL;
};
////////////////////////////////////////////////
// Vertex Shader - Main Function
///////////////////////////////////////////////
PS_INPUT VS(float4 Pos : POSITION, float4 Color : COLOR, float4 Normal : NORMAL)
{
PS_INPUT psInput;
// Pass through both the position and the color
psInput.Pos = mul( Pos, Projection );
psInput.Color = Color;
psInput.Normal = Normal;
return psInput;
}
///////////////////////////////////////////////
// Pixel Shader
///////////////////////////////////////////////
float4 PS(PS_INPUT psInput) : SV_Target
{
float4 finalColor = 0;
finalColor = saturate(dot(lightSource, psInput.Normal) * lightColor);
return finalColor;
}
// Define the technique
technique10 Render
{
pass P0
{
SetVertexShader( CompileShader( vs_4_0, VS() ) );
SetGeometryShader( NULL );
SetPixelShader( CompileShader( ps_4_0, PS() ) );
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
“我的立方体对象不会着色”到底是什么意思?最终的颜色是什么?白色的?
从您发布的内容来看,有些内容看起来有问题。首先,定义光向量的方式:
这是错误的,因为它没有标准化并且必须标准化(在 hlsl 或 c++ 代码中),否则点积毫无意义(请参阅 有关点积、几何解释的维基百科页面)。您还可以使用已经标准化的向量,例如:
[-0.577f, 0.577f, -0.577f]
或[0.0f, 0.0f, -1.0f]
并且不关心标准化。第二件事,在 VS 中,您不会根据世界矩阵变换顶点法线。这是很糟糕的,特别是如果您的光线方向已在世界空间中定义并且您的立方体法线保留在模型空间中。
好吧,这可能不是不良阴影的原因,但重要的是要提到您不能对属于不同空间的向量进行数学计算。
第三点是初始化立方体颜色的C++代码(我找不到它,以及顶点位置)。对我来说,您的代码看起来架构很糟糕,因为每个属性至少应该在同一个 CreateObject 函数中初始化。
关于着色器编码风格,我建议像这样声明
PS_INPUT
:这样
COLOR
和SV_Target
之间就不会混淆。所有非SV_*
属性均应使用TEXCOORDN
。What do you mean exactly by "my cube object won't shade" ? What's the final color? White?
From what you post, some stuff are looking wrong. First, the manner you define your light vector:
This is wrong since it's not normalized and has to be (either in hlsl or c++ code) otherwise dot product is meaningless (see wikipedia page on Dot product, Geometric interpretation). You could also use already normalized vectors like:
[-0.577f, 0.577f, -0.577f]
or[0.0f, 0.0f, -1.0f]
and don't care of normalization.Second thing, in the
VS
, you don't transform the vertex normal according to a World matrix. This is bad especially if your light direction has been defined in world-space and your cube normals stay in model-space.Well this is maybe not the cause of the bad shading, but it's important to mention you can't do math on vectors that belong to different spaces.
Third point is the c++ code that initialize cube colors (I can't find it, as well as vertice positions). To me your code looks badly architectured since every attributes should be at least initialized in the same
CreateObject
function.About shader coding style, I would recommend declaring
PS_INPUT
like this:So there is no confusion with between
COLOR
andSV_Target
. All nonSV_*
attributes should useTEXCOORDN
.