Lighting a cube with a shader issue - c++
i've been following tutorials on directx 11 with a book and am now trying to give my code some lighting effects with a shader. But the problem is that it only shows the back buffer and doens't seem te make use of the lighting shader file at all. I am trying to light up a cube. Thanks for the help already.
HLSL:
struct DirectionalLight
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float3 Direction;
float pad;
};
struct PointLight
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float3 Position;
float Range;
float3 Att;
float pad;
};
struct SpotLight
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float3 Position;
float Range;
float3 Direction;
float Spot;
float3 Att;
float pad;
};
struct Material
{
float4 Ambient;
float4 Diffuse;
float4 Specular;
float4 Reflect;
};
void ComputeDirectionalLight( Material mat, DirectionalLight L, float3 normal, float3 toEye, out float4 ambient, out float4 diffuse, out float4 spec)
{
ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
spec = float4(0.0f, 0.0f, 0.0f, 0.0f);
float3 lightVec = -L.Direction;
ambient = mat.Ambient * L.Ambient;
float diffuseFactor = dot(lightVec, normal);
[flatten]
if( diffuseFactor > 0.0f )
{
float3 v = reflect(-lightVec, normal);
float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);
diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
spec = specFactor * mat.Specular * L.Specular;
}
}
void ComputePointLight(Material mat, PointLight L, float3 pos, float3 normal, float3 toEye, out float4 ambient, out float4 diffuse, out float4 spec)
{
ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
spec = float4(0.0f, 0.0f, 0.0f, 0.0f);
float3 LightVec = L.Position - pos;
float d = length(LightVec);
if( d > L.Range )
return;
LightVec /= d;
ambient = mat.Ambient * L.Ambient;
float diffuseFactor = dot(LightVec, normal);
[flatten]
if(diffuseFactor > 0.0f)
{
float3 v = reflect(-LightVec, normal);
float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);
diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
spec = specFactor * mat.Specular * L.Specular;
}
float att = 1.0f / dot(L.Att, float3(1.0f, d, d*d));
diffuse *= att;
spec *= att;
}
void ComputeSpotLight(Material mat, SpotLight L, float3 pos, float3 normal, float3 toEye, out float4 ambient, out float4 diffuse, out float4 spec)
{
ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
spec = float4(0.0f, 0.0f, 0.0f, 0.f);
float3 LightVec = L.Position - pos;
float d = length(LightVec);
if( d > L.Range )
return;
LightVec /= d;
ambient = mat.Ambient * L.Ambient;
float diffuseFactor = dot(LightVec, normal);
[flatten]
if( diffuseFactor > 0.0f )
{
float3 v = reflect(-LightVec, normal);
float specFactor = pow(max(dot(v, toEye), 0.0f), mat.Specular.w);
diffuse = diffuseFactor * mat.Diffuse * L.Diffuse;
spec = specFactor * mat.Specular * L.Specular;
}
float spot = pow(max(dot(-LightVec, L.Direction), 0.0f), L.Spot);
float att = spot / dot(L.Att, float3(1.0f, d, d*d));
ambient *= spot;
diffuse *= att;
spec *= att;
}
cbuffer cbPerFrame
{
DirectionalLight gDirLight;
PointLight gPointLight;
SpotLight gSpotLight;
float3 gEyePosW;
};
cbuffer cbPerObject
{
float4x4 gWorld;
float4x4 gWorldInvTranspose;
float4x4 gWorldViewProj;
Material gMaterial;
};
struct VertexIn
{
float3 PosL : POSITION;
float3 NormalL : NORMAL;
};
struct VertexOut
{
float4 PosH : SV_POSITION;
float3 PosW : POSITION;
float3 NormalW: NORMAL;
};
VertexOut VS(VertexIn vin)
{
VertexOut vout;
vout.PosW = mul(float4(vin.PosL, 1.0f), gWorld).xyz;
vout.NormalW = mul(vin.NormalL, (float3x3)gWorldInvTranspose);
vout.PosH = mul(float4(vin.PosL, 1.0f), gWorldViewProj);
return vout;
}
float4 PS(VertexOut pin) : SV_Target
{
pin.NormalW = normalize(pin.NormalW);
float3 toEyeW = normalize(gEyePosW - pin.PosW);
float4 ambient = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 diffuse = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 spec = float4(0.0f, 0.0f, 0.0f, 0.0f);
float4 A, D, S;
ComputeDirectionalLight(gMaterial, gDirLight, pin.NormalW, toEyeW, A, D, S);
ambient += A;
diffuse += D;
spec += S;
ComputePointLight(gMaterial, gPointLight, pin.PosW, pin.NormalW, toEyeW, A, D, S);
ambient += A;
diffuse += D;
spec += S;
ComputeSpotLight(gMaterial, gSpotLight, pin.PosW, pin.NormalW, toEyeW, A, D, S);
ambient += A;
diffuse += D;
spec += S;
float4 litColor = ambient + diffuse + spec;
litColor.a = gMaterial.Diffuse.a;
return litColor;
}
Code in my cpp file:
struct Vertex
{
XMFLOAT3 Pos;
XMFLOAT3 Normal;
};
struct CBUFFER{ XMMATRIX gWorldViewProj; };
class BoxApp : public Framework_App
{
public:
BoxApp(HINSTANCE hInstance);
~BoxApp();
bool Init();
void OnResize();
void UpdateScene(float dt);
void DrawScene();
void OnMouseDown(WPARAM BtnState, int x, int y);
void OnMouseUp(WPARAM BtnState, int x, int y);
void OnMouseMove(WPARAM BtnState, int x, int y);
private:
void BuildGeometryBuffers();
void BuildFX();
private:
ID3D11Buffer* mBoxVB;
ID3D11Buffer* mBoxIB;
ID3D11Buffer* mBoxCB = nullptr;
ID3D11VertexShader* pVS;
ID3D11PixelShader* pPS;
ID3D11InputLayout* mInputLayout;
XMFLOAT4X4 mWorld;
XMFLOAT4X4 mView;
XMFLOAT4X4 mProj;
XMFLOAT3 mEyePosW;
XMFLOAT3 GetNormal(float x, float z)const;
//licht variablen
DirectionalLight mDirLight;
PointLight mPointLight;
SpotLight mSpotLight;
Material mLandmat;
Material mWavesmat;
float mTheta;
float mPhi;
float mRadius;
float GetHeight(float x, float z)const;
POINT mLastMousePos;
};
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
PSTR cmdLine, int showCmd)
{
BoxApp theApp(hInstance);
if (!theApp.Init())
return 0;
return theApp.App_Run();
}
BoxApp::BoxApp(HINSTANCE hInstance)
: Framework_App(hInstance), mBoxVB(0), mBoxIB(0), mBoxCB(0) ,pVS(0), pPS(0), mInputLayout(0), mEyePosW(0.0f, 0.0f, 0.0f),
mTheta(1.5f*MathTools::HalfTau), mPhi(0.25f*MathTools::HalfTau), mRadius(5.0f)
{
mLastMousePos.x = 0;
mLastMousePos.y = 0;
XMMATRIX I = XMMatrixIdentity();
XMStoreFloat4x4(&mWorld, I);
XMStoreFloat4x4(&mView, I);
XMStoreFloat4x4(&mProj, I);
//directional light
mDirLight.Ambient = XMFLOAT4(0.2f, 0.2f, 0.2f, 1.0f);
mDirLight.Diffuse = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mDirLight.Specular = XMFLOAT4(0.5f, 0.5f, 0.5f, 1.0f);
mDirLight.Direction = XMFLOAT3(0.57735f, -0.57735f, 0.57735f);
//point light
mPointLight.Ambient = XMFLOAT4(0.3f, 0.3, 0.3f, 1.0f);
mPointLight.Diffuse = XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f);
mPointLight.Specular = XMFLOAT4(0.7f, 0.7f, 0.7f, 1.0f);
mPointLight.Att = XMFLOAT3(0.0f, 0.1f, 0.0f);
mPointLight.Range = 25.0f;
//spot light
mSpotLight.Ambient = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
mSpotLight.Diffuse = XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f);
mSpotLight.Specular = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
mSpotLight.Att = XMFLOAT3(1.0f, 0.0f, 0.0f);
mSpotLight.Spot = 96.0f;
mSpotLight.Range = 1000.0f;
//materials
mLandmat.Ambient = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
mLandmat.Diffuse = XMFLOAT4(0.48f, 0.77f, 0.46f, 1.0f);
mLandmat.Specular = XMFLOAT4(0.2f, 0.2f, 0.2f, 16.0f);
}
BoxApp::~BoxApp()
{
ReleaseCOM(mBoxVB);
ReleaseCOM(mBoxIB);
ReleaseCOM(mBoxCB);
ReleaseCOM(pVS);
ReleaseCOM(pPS);
ReleaseCOM(mInputLayout);
}
bool BoxApp::Init()
{
if (!Framework_App::App_Init())
return false;
BuildGeometryBuffers();
BuildFX();
return true;
}
void BoxApp::OnResize()
{
Framework_App::OnResize();
// The window resized, so update the aspect ratio and recompute the projection matrix.
XMMATRIX P = XMMatrixPerspectiveFovLH(0.25f*MathTools::HalfTau, AspectRatio(), 1.0f, 1000.0f);
XMStoreFloat4x4(&mProj, P);
}
void BoxApp::UpdateScene(float dt)
{
// Convert Spherical to Cartesian coordinates.
float x = mRadius*sinf(mPhi)*cosf(mTheta);
float z = mRadius*sinf(mPhi)*sinf(mTheta);
float y = mRadius*cosf(mPhi);
mEyePosW = XMFLOAT3(x, y ,z);
// Build the view matrix.
XMVECTOR pos = XMVectorSet(x, y, z, 1.0f);
XMVECTOR target = XMVectorZero();
XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
XMMATRIX V = XMMatrixLookAtLH(pos, target, up);
XMStoreFloat4x4(&mView, V);
//update lights
mPointLight.Position.x = 70.0f*cosf(0.2f*mTimer.Totaltime());
mPointLight.Position.z = 70.0f*sinf(0.2f*mTimer.Totaltime());
mPointLight.Position.y = MathTools::Max(GetHeight(mPointLight.Position.x, mPointLight.Position.z), -3.0f) + 10.0f;
mSpotLight.Position = mEyePosW;
XMStoreFloat3(&mSpotLight.Direction, XMVector3Normalize(target - pos));
}
void BoxApp::DrawScene()
{
MainDevContext->ClearRenderTargetView(mRenderTargetView, reinterpret_cast<const float*>(&Colors::LightSteelBlue));
MainDevContext->ClearDepthStencilView(mDepthStencilView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
MainDevContext->IASetInputLayout(mInputLayout);
MainDevContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
UINT stride = sizeof(Vertex);
UINT offset = 0;
MainDevContext->IASetVertexBuffers(0, 1, &mBoxVB, &stride, &offset);
MainDevContext->IASetIndexBuffer(mBoxIB, DXGI_FORMAT_R32_UINT, 0);
// Set constants
XMMATRIX world = XMLoadFloat4x4(&mWorld);
XMMATRIX view = XMLoadFloat4x4(&mView);
XMMATRIX proj = XMLoadFloat4x4(&mProj);
XMMATRIX worldViewProj = world*view*proj;
XMMATRIX worldViewProjTRNS = XMMatrixTranspose(worldViewProj);
CBUFFER cBuffer;
cBuffer.gWorldViewProj = worldViewProjTRNS;
MainDevContext->UpdateSubresource(mBoxCB, 0, 0, &cBuffer, 0, 0);
MainDevContext->DrawIndexed(36, 0, 0);
mSwapChain->Present(0, 0);
}
void BoxApp::OnMouseDown(WPARAM BtnState, int x, int y)
{
mLastMousePos.x = x;
mLastMousePos.y = y;
SetCapture(FrmeWrkMainWnd);
}
void BoxApp::OnMouseUp(WPARAM BtnState, int x, int y)
{
ReleaseCapture();
}
void BoxApp::OnMouseMove(WPARAM BtnState, int x, int y)
{
if ((BtnState & MK_LBUTTON) != 0)
{
// Make each pixel correspond to a quarter of a degree.
float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
// Update angles based on input to orbit camera around box.
mTheta += dx;
mPhi += dy;
// Restrict the angle mPhi.
mPhi = MathTools::Clamp(mPhi, 0.1f, MathTools::HalfTau - 0.1f);
}
else if ((BtnState & MK_RBUTTON) != 0)
{
// Make each pixel correspond to 0.005 unit in the scene.
float dx = 0.005f*static_cast<float>(x - mLastMousePos.x);
float dy = 0.005f*static_cast<float>(y - mLastMousePos.y);
// Update the camera radius based on input.
mRadius += dx - dy;
// Restrict the radius.
mRadius = MathTools::Clamp(mRadius, 3.0f, 15.0f);
}
mLastMousePos.x = x;
mLastMousePos.y = y;
}
void BoxApp::BuildGeometryBuffers()
{
// Create vertex buffer
Vertex vertices[] =
{
{ XMFLOAT3(-1.0f, -1.0f, -1.0f), (const float*)&Colors::White },
{ XMFLOAT3(-1.0f, +1.0f, -1.0f), (const float*)&Colors::Black },
{ XMFLOAT3(+1.0f, +1.0f, -1.0f), (const float*)&Colors::Red },
{ XMFLOAT3(+1.0f, -1.0f, -1.0f), (const float*)&Colors::Green },
{ XMFLOAT3(-1.0f, -1.0f, +1.0f), (const float*)&Colors::Blue },
{ XMFLOAT3(-1.0f, +1.0f, +1.0f), (const float*)&Colors::Yellow },
{ XMFLOAT3(+1.0f, +1.0f, +1.0f), (const float*)&Colors::Cyan },
{ XMFLOAT3(+1.0f, -1.0f, +1.0f), (const float*)&Colors::Magneta }
};
D3D11_BUFFER_DESC vbd;
vbd.Usage = D3D11_USAGE_IMMUTABLE;
vbd.ByteWidth = sizeof(Vertex)* 8;
vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vbd.CPUAccessFlags = 0;
vbd.MiscFlags = 0;
vbd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA vinitData;
vinitData.pSysMem = vertices;
MainD3DDevice->CreateBuffer(&vbd, &vinitData, &mBoxVB);
// Create the index buffer
UINT indices[] = {
// front face
0, 1, 2,
0, 2, 3,
// back face
4, 6, 5,
4, 7, 6,
// left face
4, 5, 1,
4, 1, 0,
// right face
3, 2, 6,
3, 6, 7,
// top face
1, 5, 6,
1, 6, 2,
// bottom face
4, 0, 3,
4, 3, 7
};
D3D11_BUFFER_DESC ibd;
ibd.Usage = D3D11_USAGE_IMMUTABLE;
ibd.ByteWidth = sizeof(UINT)* 36;
ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
ibd.CPUAccessFlags = 0;
ibd.MiscFlags = 0;
ibd.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA iinitData;
iinitData.pSysMem = indices;
MainD3DDevice->CreateBuffer(&ibd, &iinitData, &mBoxIB);
}
float BoxApp::GetHeight(float x, float z)const
{
return 0.3f*(z*sinf(0.1f*x) + x*cosf(0.1*z));
}
XMFLOAT3 BoxApp::GetNormal(float x, float z)const
{
XMFLOAT3 n(-0.03f*z*cosf(0.1f*x) - 0.3f*cosf(0.1f*z), 1.0f, -0.3f*sinf(0.1f*x) - 0.03f*x*sinf(0.1f*z));
XMVECTOR unitNormal = XMVector3Normalize(XMLoadFloat3(&n));
XMStoreFloat3(&n, unitNormal);
return n;
}
void BoxApp::BuildFX()
{
ID3D10Blob* VS;
ID3D10Blob* PS;
D3DX11CompileFromFile((LPSTR)"mColor.shader",0,0, "VS", "vs_4_0", 0, 0, 0, &VS, 0, 0);
D3DX11CompileFromFile((LPSTR)"mColor.shader", 0, 0, "PS", "ps_4_0", 0, 0, 0, &PS, 0, 0);
MainD3DDevice->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
MainD3DDevice->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
MainDevContext->VSSetShader(pVS, 0, 0);
MainDevContext->PSSetShader(pPS, 0, 0);
D3D11_INPUT_ELEMENT_DESC vertexDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
{ "NORMAL", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
MainD3DDevice->CreateInputLayout(vertexDesc, 2, VS->GetBufferPointer(), VS->GetBufferSize() ,&mInputLayout);
MainDevContext->IASetInputLayout(mInputLayout);
D3D11_BUFFER_DESC bd;
ZeroMemory(&bd, sizeof(bd));
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof(CBUFFER);
bd.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
MainD3DDevice->CreateBuffer(&bd, nullptr, &mBoxCB);
MainDevContext->VSSetConstantBuffers(0, 1, &mBoxCB);
}
I Think you have alot of errors in this code.
Folow these tutorials aswell, It might be easier to get the whole view then:
http://web.archive.org/web/20140213145557/http://rastertek.com/tutdx11.html
One example, you run BuildFX() at the start, I am pretty sure you should set these two functions every frame
MainDevContext->VSSetShader(pVS, 0, 0);
MainDevContext->PSSetShader(pPS, 0, 0);
Have you succeded to Rendered a cube with pure colors yet? If so you should just build from there.
There is alot of code to mention but the last 5 functions i run every frame is those:
deviceContext->IASetInputLayout(m_layout);
deviceContext->VSSetShader(m_vertexShader, NULL, 0);
deviceContext->PSSetShader(m_pixelShader, NULL, 0);
deviceContext->PSSetSamplers(0, 1, &m_sampleState);
deviceContext->DrawIndexed(indexCount, 0, 0);
Read the link and reduce down your errors. I havent read all of your code.
Related
Trouble with constant buffers
im trying to use constant buffers in d3d11 but turns out that when the shader multiplies the pos vector with the matrix it doesnt return anything and i get a black screen,i have tried everything that i found on tutorials but i had nothing,here is the code: D3D11_BUFFER_DESC udesc; ZeroMemory(&udesc,sizeof(D3D11_BUFFER_DESC)); udesc.Usage = D3D11_USAGE_DEFAULT; udesc.CPUAccessFlags = 0; udesc.ByteWidth = sizeof(uniformsperobj); udesc.MiscFlags = 0; udesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; hr = dispositivo->CreateBuffer(&udesc,NULL,&uniformbuffer); //draw frame function// model = XMMatrixIdentity(); campos = XMVectorSet(0.0f, 0.0f, -0.5f, 0.0f); camtarget = XMVectorSet(0.0f, 0.0f, 0.0f, 0.0f); camup = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f); view = XMMatrixLookAtLH(posdecam, objdecam, arrdecam); proyection = XMMatrixPerspectiveFovLH(0.4f * 3.14f, (float)WINDOW_WIDTH /WINDOW_HEIGHT, 1.0, 1000.0f); XMMATRIX MVP = model*view*proyection; upo.MVP = XMMatrixTranspose(MVP); context->UpdateSubresource(uniformbuffer,0,NULL,&upo,0,0); context->VSSetConstantBuffers(0,1,&uniformbuffer) /* ********************************shaders.fx*********************************************** */ cbuffer uniformesporobjeto { float4x4 MVP; }; struct vertex { float4 Pos : SV_POSITION; float4 Color : COLOR; }; vertex vshader(float4 position : POSITION, float4 color : COLOR) { vertex output; output.Pos = mul(position, MVP); output.Color = color; return output; } float4 pshader(vertex input) : SV_TARGET { return input.Color; } sorry if i posted too much code but the problem is that i dont really know were the error is because im stupid
Shadow map - some shadows get cut off
I'm working on a voxel engine and my shadow map has some strange behavior. When I turn my directional light to a certain angle, some shadows are cut off. here a pic how it looks like and my shadow map. this is how I render my shadows: glDisable(GL_CULL_FACE); glEnable(GL_DEPTH_TEST); glViewport(0, 0, SHADOW_WIDTH_, SHADOW_HEIGHT_); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO_); glClearColor(0.1f, 0.1f, 0.1f, 1.0f); glClear(GL_DEPTH_BUFFER_BIT); glm::mat4 lightProjection, lightView; float near_plane = 1.0f, far_plane = 200.0f; //lightProjection = glm::perspective(glm::radians(45.0f), (GLfloat)SHADOW_WIDTH_ / (GLfloat)SHADOW_HEIGHT_, near_plane, far_plane); // note that if you use a perspective projection matrix you'll have to change the light position as the current light position isn't enough to reflect the whole scene lightProjection = glm::ortho<float>(-100.0f, 100.0f, -100.0f, 100.0f, near_plane, far_plane); glm::vec3 lightPos; lightPos.x = LightControl_->GetLightPosition(LightControl_->GetDirectionalLightNames()[0]->ToString()).X; lightPos.y = LightControl_->GetLightPosition(LightControl_->GetDirectionalLightNames()[0]->ToString()).Y; lightPos.z = LightControl_->GetLightPosition(LightControl_->GetDirectionalLightNames()[0]->ToString()).Z; glm::vec3 target; target.x = LightControl_->GetLightDirection(LightControl_->GetDirectionalLightNames()[0]->ToString()).X; target.y = LightControl_->GetLightDirection(LightControl_->GetDirectionalLightNames()[0]->ToString()).Y; target.z = LightControl_->GetLightDirection(LightControl_->GetDirectionalLightNames()[0]->ToString()).Z; lightView = glm::lookAt(lightPos, target+lightPos, glm::vec3(0.0, 1.0, 0.0)); *lightSpaceMatrix = lightProjection * lightView; // render scene from light's point of view shaderProgram.Use(); glm::mat4 model = glm::mat4(1.0f); glUniformMatrix4fv(shaderProgram.GetUniform("lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(*lightSpaceMatrix)); glUniformMatrix4fv(shaderProgram.GetUniform("u_model"), 1, GL_FALSE, glm::value_ptr(model)); glViewport(0, 0, SHADOW_WIDTH_, SHADOW_HEIGHT_); glBindFramebuffer(GL_FRAMEBUFFER, depthMapFBO_); glClear(GL_DEPTH_BUFFER_BIT); auto tmp = GraphicControl_->GetVoxelBuffer("test"); tmp.ClearVoxelRenderList(); tmp.VoxelBufferData(chunksForRendering); RenderVoxelBuffer(tmp,shaderProgram); glBindFramebuffer(GL_FRAMEBUFFER, GraphicControl_->GetDefaultFrameBuffer()->getFBO()); glViewport(0, 0, 1920, 1080); glEnable(GL_CULL_FACE); shadow map vert: #version 450 core layout(location = 0) in uint all_voxel_data; out VsOut { mat4 lightSpaceMatrix; mat4 model; vec3 u_chunk_location; } vs_out; uniform mat4 lightSpaceMatrix; uniform mat4 model; uniform vec3 u_chunk_location; const int AllVoxelDataMask[6] = { 0xF8000000, // x-Position 0x07C00000, // y-Position 0x003E0000, // z-Position 0x0001F800, // culled Faces 0x00000700, // Render Options 0x000000FF // color Index for Palette }; vec4 DecodePosition(uint encoded_position) { float x = float((encoded_position & AllVoxelDataMask[0]) >> 27) + u_chunk_location.x * 32; float y = float((encoded_position & AllVoxelDataMask[1]) >> 22) + u_chunk_location.y * 32; float z = float((encoded_position & AllVoxelDataMask[2]) >> 17) + u_chunk_location.z * 32; return vec4(x, y, z, 1.0); } void main() { vs_out.lightSpaceMatrix=lightSpaceMatrix; vs_out.u_chunk_location=u_chunk_location; vs_out.model=model; gl_Position = DecodePosition(all_voxel_data); } shadow map geom: #version 450 core layout(points) in; layout(triangle_strip, max_vertices = 36) out; #define halfVoxelSize 0.5 // 2-------6 // /| /| // 3-------7 | // | 0-----|-4 // |/ |/ // 1-------5 const vec4 VoxelVertices[8] = { vec4(-halfVoxelSize, -halfVoxelSize, -halfVoxelSize, 0.0f), // Back-Bot-Left vec4(-halfVoxelSize, -halfVoxelSize, halfVoxelSize, 0.0f), // Front-Bot-Left vec4(-halfVoxelSize, halfVoxelSize, -halfVoxelSize, 0.0f), // Back-Top-Left vec4(-halfVoxelSize, halfVoxelSize, halfVoxelSize, 0.0f), // Front-Top-Left vec4(halfVoxelSize, -halfVoxelSize, -halfVoxelSize, 0.0f), // Back-Bot-Right vec4(halfVoxelSize, -halfVoxelSize, halfVoxelSize, 0.0f), // Front-Bot-Right vec4(halfVoxelSize, halfVoxelSize, -halfVoxelSize, 0.0f), // Back-Top-Right vec4(halfVoxelSize, halfVoxelSize, halfVoxelSize, 0.0f) // Front-Top-Right }; const vec3 VoxelNormals[6] = { vec3(-1.0f, 0.0f, 0.0f), // Left-X-Axis vec3( 1.0f, 0.0f, 0.0f), // Right-X-Axis vec3( 0.0f, -1.0f, 0.0f), // Bot-Y-Axis vec3( 0.0f, 1.0f, 0.0f), // Top-Y-Axis vec3( 0.0f, 0.0f, -1.0f), // Back-Z-Axis vec3( 0.0f, 0.0f, 1.0f) // Front-Z-Axis }; in VsOut { mat4 lightSpaceMatrix; mat4 model; vec3 u_chunk_location; } gs_in[]; out GsOut { mat4 lightSpaceMatrix; mat4 model; vec3 u_chunk_location; } gs_out; void AddTriangle(vec4 a, vec4 b, vec4 c) { gl_Position = gs_in[0].lightSpaceMatrix * a; EmitVertex(); gl_Position = gs_in[0].lightSpaceMatrix * b; EmitVertex(); gl_Position = gs_in[0].lightSpaceMatrix * c; EmitVertex(); EndPrimitive(); } void AddQuad(vec4 a, vec4 b, vec4 c, vec4 d, vec3 normal) { vec4 center = gl_in[0].gl_Position; // Zugriff auf das erste Voxel, was gleichzeitig unser einzigstes Voxel ist. Weil gl_Points verwendet wird. gs_out.model=gs_in[0].model; if (dot(-(gs_in[0].lightSpaceMatrix * center), (gs_in[0].lightSpaceMatrix * vec4(normal, 0.0f))) <= 0.0) return; // a-------d // | \ | // | \ | // b-------c AddTriangle(center + a, center + b, center + c); AddTriangle(center + c, center + d, center + a); } void main() { // 0-------3 // | | // | | // 1-------2 AddQuad(VoxelVertices[3], VoxelVertices[1], VoxelVertices[5], VoxelVertices[7], VoxelNormals[5]); // Front-Surface AddQuad(VoxelVertices[2], VoxelVertices[0], VoxelVertices[1], VoxelVertices[3], VoxelNormals[0]); // Left-Surface AddQuad(VoxelVertices[7], VoxelVertices[5], VoxelVertices[4], VoxelVertices[6], VoxelNormals[1]); // Right-Surface AddQuad(VoxelVertices[2], VoxelVertices[3], VoxelVertices[7], VoxelVertices[6], VoxelNormals[3]); // Top-Surface AddQuad(VoxelVertices[1], VoxelVertices[0], VoxelVertices[4], VoxelVertices[5], VoxelNormals[2]); // Bot-Surface AddQuad(VoxelVertices[6], VoxelVertices[4], VoxelVertices[0], VoxelVertices[2], VoxelNormals[4]); // Back-Surface } shadow map frag #version 450 core out vec4 outColor; void main() { //gl_FragDepth = gl_FragCoord.z; } does anyone know what's wrong?
OpenGL - Getting camera to move
I'm having trouble with my OpenGL game where I can't get the camera to move. I am unable to use GLFW, GLUT and glulookat(). Here is my code, what's wrong? P.S everything works except the camera movement meaning the game plays and works perfectly, just cant move the camera. My Camera Code: #include "SpriteRenderer.h" #include <glm/glm.hpp> #include <glm/gtc/matrix_transform.hpp> class Camera { private: Shader shader; GLfloat angle = -90.f; glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f), cameraPosition = glm::vec3(0.0f, 0.0f, 0.1f), cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); glm::mat4 viewMatrix; // recompute the view matrix from the camera variables void updateMatrix() { viewMatrix = glm::lookAt(cameraPosition, cameraPosition + cameraFront, cameraUp); } // default constructor void defaultNew() { cameraPosition = glm::vec3(0.0f, 0.0f, 0.1f); cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); updateMatrix(); } public: Camera() { defaultNew(); } Camera(Shader &shader) { this->shader = shader; defaultNew(); } glm::mat4 GetViewMatrix() const { // if your view matrix is always up-to-date, just return it directly return viewMatrix; } // get functions glm::vec3 GetCameraPosition() const { return cameraPosition; } // .. same for Front and Up // set functions // call updateMatrix every time you update a variable void SetCameraPosition(glm::vec3 pos) { cameraPosition = pos; updateMatrix(); } // .. same for Front and Up // no need to use this-> all the time virtual void Draw() { this->shader.Use(); this->shader.SetMatrix4("view", viewMatrix); } }; My Shader Code: Shader &Use(){ glUseProgram(this->ID); return *this; } void SetMatrix4(const GLchar *name, const glm::mat4 &matrix, GLboolean useShader = false) { if (useShader)this->Use(); glUniformMatrix4fv(glGetUniformLocation(this->ID, name), 1, GL_FALSE, glm::value_ptr(matrix)); } My Game Code: Camera *View; projection2 = glm::perspective(glm::radians(44.0f), (float)this->Width / (float)this->Width, 0.1f, 100.0f); AssetController::LoadShader("../src/Shaders/Light.vert", "../src/Shaders/Light.frag", "light"); AssetController::GetShader("light").SetMatrix4("projection", projection2); View = new Camera(AssetController::GetShader("light")); (...) GLfloat velocity = playerSpeed * deltaTime; glm::vec3 camPosition; // Update Players Position if (movingLeft) { if (Player->Position.x >= 0) { Player->Position.x -= velocity; if (Ball->Stuck) Ball->Position.x -= velocity; camPosition = View->GetCameraPosition(); camPosition.x -= velocity / 2; View->SetCameraPosition(camPosition); } } else if (movingRight) { if (Player->Position.x <= this->Width - Player->Size.x) { Player->Position.x += velocity; if (Ball->Stuck) Ball->Position.x += velocity; camPosition = View->GetCameraPosition(); camPosition.x += velocity / 2; View->SetCameraPosition(camPosition); } } (...) GameOver->Draw(*Renderer); View->Draw(); My Shaders: .vert: #version 440 core layout (location = 0) in vec3 aPos; layout (location = 1) in vec2 aTexCoord; out vec2 TexCoord; uniform mat4 model; uniform mat4 view; uniform mat4 projection; void main() { gl_Position = projection * view * model * vec4(aPos, 1.0f); TexCoord = vec2(aTexCoord.x, aTexCoord.y); } .frag: #version 440 core out vec4 FragColor; in vec2 TexCoord; // texture samplers uniform sampler2D texture1; uniform sampler2D texture2; void main() { // linearly interpolate between both textures (80% container, 20% awesomeface) FragColor = mix(texture(texture1, TexCoord), texture(texture2, TexCoord), 0.2); }
The problem is that you only update local position variable cameraPosition, and not the view matrix, which is passed to OpenGL during rendering. It is also a bad habit to make the camera variables and matrix public, as they can potentially be modified incorrectly or out-of-sync (as you are doing). Instead, you could write a pair of get/set functions: class Camera { private: Shader shader; GLfloat angle = -90.f; glm::vec3 cameraFront = glm::vec3(0.0f, 0.0f, -1.0f), cameraPosition = glm::vec3(0.0f, 0.0f, 0.1f), cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); glm::mat4 viewMatrix; // recompute the view matrix from the camera variables void updateMatrix() { viewMatrix = glm::lookAt(cameraPosition, cameraPosition + cameraFront, cameraUp); } // default constructor void defaultNew() { cameraPosition = glm::vec3(0.0f, 0.0f, 0.1f); cameraFront = glm::vec3(0.0f, 0.0f, -1.0f); cameraUp = glm::vec3(0.0f, 1.0f, 0.0f); updateMatrix(); } public: Camera() { defaultNew(); } Camera(Shader &shader) { this->shader = shader; defaultNew(); } glm::mat4 GetViewMatrix() const { // if your view matrix is always up-to-date, just return it directly return viewMatrix; } // get functions glm::vec3 GetCameraPosition() const { return cameraPosition; } // .. same for Front and Up // set functions // call updateMatrix every time you update a variable void SetCameraPosition(glm::vec3 p) { cameraPosition = p; updateMatrix(); } // .. same for Front and Up // no need to use this-> all the time virtual void Draw() { shader.Use(); shader.SetMatrix4("view", viewMatrix); } }; And then when you update the camera position, simply use these functions instead of the exposed variables: view->SetCameraPosition(view->GetCameraPosition() + velocity / 2.0f); This will make sure that the draw calls always use the updated view matrix instead of the initial one (which was the case before and the source of your troubles).
Point to quad expansion with Geometry Shader
I am new to the geometry shader, so I am trying to make a geometry shader that will take a point and create a quad with texture coordinates, just as an example to see how the geometry shader works. Here is the code I have written: Texture2D txDiffuse : register( t0 ); SamplerState samAnisotropic { Filter = ANISOTROPIC; MaxAnisotropy = 4; }; cbuffer cbFixed { // // Compute texture coordinates to stretch texture over quad. // float2 gTexC[4] = { float2(0.0f, 1.0f), float2(0.0f, 0.0f), float2(1.0f, 1.0f), float2(1.0f, 0.0f) }; }; cbuffer ConstantBuffer : register( b0 ) { matrix World; matrix View; matrix Projection; } struct VS_INPUT { float3 Pos : POSITION; }; struct VertexOut { float3 Pos : POSITION; }; struct GeoOut { float4 PosH : SV_POSITION; float2 Tex : TEXCOORD; uint PrimID : SV_PrimitiveID; }; VertexOut VS( VS_INPUT input ) { VertexOut output; output.Pos = input.Pos; return output; } [maxvertexcount(4)] void GS(point VertexOut gin[1], uint primID : SV_PrimitiveID, inout TriangleStream<GeoOut> tristream) { float4 v[4]; v[0] = float4(gin[0].Pos + float3(1.0f, -1.0f, 0.0f), 1.0f); v[1] = float4(gin[0].Pos + float3(1.0f, 1.0f, 0.0f), 1.0f); v[2] = float4(gin[0].Pos + float3(-1.0f, -1.0f, 0.0f), 1.0f); v[3] = float4(gin[0].Pos + float3(-1.0f, 1.0f, 0.0f), 1.0f); GeoOut gout; [unroll] for (int i = 0; i < 4; i++) { gout.PosH = mul(v[i], World); gout.PosH = mul(v[i], View); gout.PosH = mul(v[i], Projection); gout.Tex = gTexC[i]; gout.PrimID = primID; tristream.Append(gout); } } float4 PS( GeoOut input) : SV_Target { //return txDiffuse.Sample( samAnisotropic, input.Tex ); return float4( 1.0f, 1.0f, 1.0f, 1.0f ); } When I compile this code, I get a blank screen. At first I thought it may be a texture problem, so I tried having the pixel shader output white, but it did not help. Next I thought it may not show because of the way the triangle is wound, so I disabled back face culling, but it still did not help. I'm not sure what to try next. Any ideas on the problem?
I have not ever worked with geometry shaders, but I think the way you're calculating gout.PosH is wrong. It should be float4 p = mul(v[i], World); p = mul(p, View); p = mul(p, Projection); gout.PosH = p; See where you went wrong? Hope this helps.
Texture transform matrix in a constantbuffer not working properly
I'm trying to clip a texture by hardcoding the texture coordinates through 0 and 1, and then sending a constantbuffer containing a 3x3 texture transform matrix to the vertexshader. However, the texture is not rendering as I expected it to. I'm not sure where I went wrong. Could someone help? See code below. For testing, I'm trying to use an Identity matrix to keep the texture coordinates untouched, but the texture shows up transformed in a very weird way. This is the texture: (the colours showing up are actually transparent areas, except the black colour and the softer red colour of the heart) Transformed texture: HLSL: cbuffer cbChangesPerFrame : register( b0 ) { matrix g_Mvp; }; cbuffer cbTexTransform : register( b2 ) { float3x3 g_TexTransform; }; Texture2D g_ColorMap : register(t0); SamplerState g_ColorSampler : register(s0); struct VS_Input { float4 pos : POSITION0; float2 tex0 : TEXCOORD0; }; struct PS_Input { float4 pos : SV_POSITION0; float2 tex0 : TEXCOORD0; }; PS_Input VS_Main(VS_Input vertex) { PS_Input vsOut = (PS_Input)0; vsOut.pos = mul(vertex.pos,g_Mvp); //vsOut.tex0 = vertex.tex0; float3 coord = float3(vertex.tex0, 1.0); coord = mul(coord, g_TexTransform); vsOut.tex0 = coord.xy ; return vsOut; } float4 PS_Main( PS_Input frag ) : SV_TARGET { return g_ColorMap.Sample( g_ColorSampler, frag.tex0 ); } VBuffer hardcoded: Vertex::PosTex vertices[]= { {XMFLOAT3( 0.5f, 0.5f, 1.0f ), XMFLOAT2( 1.0f, 0.0f )}, {XMFLOAT3( 0.5f, -0.5f, 1.0f ), XMFLOAT2( 1.0f, 1.0f )}, {XMFLOAT3( -0.5f, -0.5f, 1.0f ), XMFLOAT2( 0.0f, 1.0f )}, {XMFLOAT3( -0.5f, -0.5f, 1.0f ), XMFLOAT2( 0.0f, 1.0f )}, {XMFLOAT3( -0.5f, 0.5f, 1.0f ), XMFLOAT2( 0.0f, 0.0f )}, {XMFLOAT3( 0.5f, 0.5f, 1.0f ), XMFLOAT2( 1.0f, 0.0f )} }; Matrix definition: XMFLOAT3X3 f3x3; f3x3.m[0][0] = 1.0f; f3x3.m[0][1] = 0.0f; f3x3.m[0][2] = 0.0f; f3x3.m[1][0] = 0.0f; f3x3.m[1][1] = 1.0f; f3x3.m[1][2] = 0.0f; f3x3.m[2][0] = 0.0f; f3x3.m[2][1] = 0.0f; f3x3.m[2][2] = 1.0f; GAME_MANAGER->GMSetTexTransformMatrix(f3x3); Game_Manager GMSetTransformMatrix() definition: void GameManager::GMSetTexTransformMatrix( const XMFLOAT3X3& rkTexTransform ) { m_pContext->UpdateSubresource(m_pTexTransformCB,0,0,&rkTexTransform,0,0); m_pContext->VSSetConstantBuffers(2,1,&m_pTexTransformCB); } Buffer Initialisation: ZeroMemory(&constDesc, sizeof(constDesc)); constDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; constDesc.ByteWidth = 48; constDesc.Usage = D3D11_USAGE_DEFAULT; result = m_pDevice->CreateBuffer(&constDesc,0,&m_pTexTransformCB);
The problem is the 16 byte alignment. An XMFLOAT3X3 is just 9 floats in a row. When this gets stored in registers, its just going to take the first four floats and put them in c0, the next four in c1, and the remaining float in c2.x. You can see this yourself with the following: cbuffer cbChangesEveryFrame : register( b1 ) { float a1 : packoffset(c0.x); float a2 : packoffset(c0.y); float a3 : packoffset(c0.z); float b1 : packoffset(c0.w); float b2 : packoffset(c1.x); float b3 : packoffset(c1.y); float c1 : packoffset(c1.z); float c2 : packoffset(c1.w); float c3 : packoffset(c2.x); }; 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, Projection ); float3 coord = float3(input.Tex, 1.0); float3x3 g_TexTransform = {a1, a2, a3, b1, b2, b3, c1, c2, c3}; coord = mul(coord, g_TexTransform); output.Tex = coord.xy; return output; } Now when you pass your XMFLOAT3X3, the texture appears normally. The problem was that because of the register allocation, your texture transform matrix became screwed up. When you look at the registers, this is how your data looks coming in: c0: 1 0 0 0 c1: 1 0 0 0 c2: 1 float3x3's are probably an array of float3's, so it would take the first three components of each register, giving you: 1, 0, 0 1, 0, 0 1, 0, 0 Its scaling your Y to 0, which is giving that wierd stretchy look. To solve this, you're going to either have to store your transform in a 4x4 matrix, or manually assign each part of the register. Switching to three float3's wouldn't work either, because they can't cross the 16-byte boundary.