我有一个问题,我的着色器代码只有在我将b1
寄存器中的像素着色器常量缓冲区设置为下面的结构时才能正常执行。我一直在寻找答案,我可能花了8个小时试图解决这个问题。似乎来自ConstantBuffer
的变量time
被放入CameraBuffer
的变量中。我认为__declspec(align(16))
修复了填充问题。我相信我也正确地填充了东西。我在整个代码中放置了注解。
// A buffer for lighting
__declspec(align(16))
struct CameraBuffer {
Vec3f position{};
Vec3f direction{};
Vec2f pad{};
};
// The buffer required for proper results, even though it shouldn't be required.
__declspec(align(16))
struct ConstantBuffer {
float time;
float period;
float amplitude;
};
// Method for drawing a sphere
void DXGLApp::drawMaterialSphere(Vec3f position, dxgl::SP_DXGLMaterial material) {
// transform data
dxgl::buffer::TransformBuffer tbuff1{};
tbuff1.world.setIdentity();
tbuff1.world.setTranslation(position);
tbuff1.view = m_camera->view();
tbuff1.proj = m_camera->proj();
m_cbLandscape->update(&tbuff1);
// setting vertex data
render()->stageInput()->setInputLayout(m_layout);
render()->stageInput()->setVertexBuffers(1, &m_mesh1->getVertexBuffer());
render()->stageInput()->setIndexBuffer(m_mesh1->getIndexBuffer());
// setting shaders
render()->stageShader()->VS_setShader(m_vs);
render()->stageShader()->PS_setShader(m_ps);
// setting cbuffers
render()->stageShader()->VS_setCBuffer(0, 1, m_cbLandscape->get());
render()->stageShader()->PS_setCBuffer(0, 1, m_cbCamera->get());
// This cbuffer, 'm_cbPostProcess' is not used in the currently bound shader,
// yet the results produced without it are incorrect.
render()->stageShader()->PS_setCBuffer(1, 1, m_cbPostProcess->get());
// sets texture slots
render()->stageShader()->PS_setMaterial(0, 6, material);
// draw
render()->stageInput()->drawIndexedTriangleList(m_mesh1->getIndices().size(), 0, 0);
// unbind
//render()->stageShader()->VS_setShader(0);
//render()->stageShader()->PS_setShader(0);
//render()->stageShader()->VS_setCBuffer(0, 0, 0);
//render()->stageShader()->PS_setCBuffer(0, 0, 0);
}
void update(long double delta) {
// updating m_cbCamera
dxgl::buffer::CameraBuffer camBuff{};
camBuff.position = m_camera->world().getTranslation();
camBuff.direction = m_camera->world().getZDirection();
m_cbCamera->update(&camBuff);
// updating m_cbPostProcess
ConstantBuffer dvbuff{};
dvbuff.time = t / 4.0f;
dvbuff.period = 0;// 8.0f;
dvbuff.amplitude = 0;// 0.0125f;
m_cbPostProcess->update(&dvbuff);
}
这是我的着色器代码。我正在尝试实现PBR。
顶点着色器
struct VS_Input {
float4 position: POSITION;
float2 texcoord: TEXCOORD;
float3 normal: NORMAL;
float3 tangent: TANGENT;
};
struct PS_Input {
float4 position: SV_POSITION;
float2 texcoord: TEXCOORD;
float3 normal: NORMAL;
float3 tangent: TANGENT;
float3 pixelPosition: POSITION;
};
cbuffer transform: register(b0) {
row_major float4x4 world;
row_major float4x4 view;
row_major float4x4 proj;
};
PS_Input main(VS_Input input) {
PS_Input output = (PS_Input)0;
output.position = mul(input.position, world);
output.position = mul(output.position, view);
output.position = mul(output.position, proj);
output.pixelPosition = mul(input.position, world);
output.texcoord = input.texcoord;
output.normal = mul(input.normal, world);
output.tangent = mul(input.tangent, world);
return output;
}
像素着色器
struct PS_Input {
float4 position: SV_POSITION;
float2 texcoord: TEXCOORD;
float3 normal: NORMAL;
float3 tangent: TANGENT;
float3 pixelPosition: POSITION;
};
cbuffer camera: register(b0) {
float4 cameraPosition;
float4 cameraDirection;
}
float PI = 3.14159265359f;
SamplerState textureSampler: register(s0);
Texture2D tex_normalMap: register(t0);
Texture2D tex_heightMap: register(t1);
Texture2D tex_albedoMap: register(t2);
Texture2D tex_metallicMap: register(t3);
Texture2D tex_roughnessMap: register(t4);
Texture2D tex_aoMap: register(t5);
float3 calculateNormals(PS_Input input) {
float3 normal = normalize(input.normal);
float3 tangent = normalize(input.tangent);
tangent = normalize(input.tangent - dot(input.tangent, input.normal) * input.normal);
float3 bitangent = normalize(cross(normal, tangent));
const float3x3 TBN = float3x3(tangent, bitangent, normal);
float3 normalSample = tex_normalMap.Sample(textureSampler, input.texcoord).rgb;
normalSample.x = 2.0f * normalSample.r - 1.0f;
normalSample.y = -2.0f * normalSample.g + 1.0f;
normalSample.z = normalSample.b;
normal = mul(normalSample, TBN);
return normal;
}
float3 fresnelSchlick(float cosTheta, float3 F0) {
if (cosTheta > 1.0f) {
cosTheta = 1.0f;
}
float p = pow(1.0f - cosTheta, 5.0f);
return F0 + (1.0f - F0) * p;
}
float DistributionGGX(float3 N, float3 H, float roughness) {
float a = roughness * roughness;
float a2 = a * a;
float NdotH = max(dot(N, H), 0.0f);
float NdotH2 = NdotH * NdotH;
float num = a2;
float denom = (NdotH2 * (a2 - 1.0f) + 1.0f);
denom = PI * denom * denom;
return num / denom;
}
float GeometrySchlickGGX(float NdotV, float roughness) {
float r = (roughness + 1.0f);
float k = (r * r) / 8.0f;
float num = NdotV;
float denom = NdotV * (1.0f - k) + k;
return num / denom;
}
float GeometrySmith(float3 N, float3 V, float3 L, float roughness) {
float NdotV = max(dot(N, V), 0.0f);
float NdotL = max(dot(N, L), 0.0f);
float ggx2 = GeometrySchlickGGX(NdotV, roughness);
float ggx1 = GeometrySchlickGGX(NdotL, roughness);
return ggx1 * ggx2;
}
float3 getPBRLighting(PS_Input input) {
float3 color = float3(0.0f, 0.0f, 0.0f);
float3 albedoSample = pow(tex_albedoMap.Sample(textureSampler, input.texcoord).rgb, 2.2333f);
float metallicSample = tex_metallicMap.Sample(textureSampler, input.texcoord).r;
float roughnessSample = tex_roughnessMap.Sample(textureSampler, input.texcoord).r;
float aoSample = tex_aoMap.Sample(textureSampler, input.texcoord).r;
float3 N = normalize(input.normal);
float3 V = normalize(cameraPosition - input.pixelPosition);
float3 F0 = float3(0.04f, 0.04f, 0.04f);
F0 = lerp(F0, albedoSample, metallicSample);
float3 lightPositions[6] = {
float3(-12.0f, 0.0f, -3.0f),
float3( -6.0f, 0.0f, -3.0f),
float3( 0.0f, 0.0f, -3.0f),
float3( 6.0f, 0.0f, -3.0f),
float3( 12.0f, 0.0f, -3.0f),
float3( 18.0f, 0.0f, -3.0f),
};
float3 lightColor = float3(1.0f, 1.0f, 1.0f);
// reflectance equation
float3 Lo = float3(0.0f, 0.0f, 0.0f);
for (int i = 0; i < 6; i++) {
// calculate per-light radiance
float3 L = normalize(lightPositions[i] - input.pixelPosition);
float3 H = normalize(V + L);
float distance = length(lightPositions[i] - input.pixelPosition);
float attenuation = 1.0f / (distance * distance);
float3 radiance = lightColor * attenuation;
// cook-torrance brdf
float NDF = DistributionGGX(N, H, roughnessSample);
float G = GeometrySmith(N, V, L, roughnessSample);
float3 F = fresnelSchlick(max(dot(H, V), 0.0f), F0);
float3 kS = F;
float3 kD = float3(1.0f, 1.0f, 1.0f) - kS;
kD *= 1.0f - metallicSample;
float3 numerator = NDF * G * F;
float denominator = 4.0f * max(dot(N, V), 0.0f) * max(dot(N, L), 0.0f) + 0.0001f;
float3 specular = numerator / denominator;
// add to outgoing radiance Lo
float NdotL = max(dot(N, L), 0.0f);
Lo += (kD * albedoSample / PI + specular) * radiance * NdotL;
}
float3 ambient = float3(0.01f, 0.01f, 0.01f) * albedoSample * aoSample;
color = ambient + Lo;
return color;
}
float4 main(PS_Input input) : SV_TARGET {
input.normal = calculateNormals(input);
float3 color = getPBRLighting(input);
// HDR tone mapping and gamma correction
float exposure = 10.0f;
float gamma = 1.0f;
float3 toneMap = float3(1.0f, 1.0f, 1.0f) - exp((-color) * exposure);
float3 toneMappedColor = pow(toneMap, float3(gamma, gamma, gamma));
return float4(toneMappedColor, 1.0f);
}
所有的东西都能编译。我这辈子都搞不懂为什么常量缓冲区不能正常工作。
包含m_cbPostProcess
的结果:https://gyazo.com/22bc8169fc5e3e772f4dafac2a78e4ed
结果已注解:https://gyazo.com/07359dd66e1d4a9dce55677b046c657d
我知道我在这里包含了很多代码,但是我认为多比少好。任何帮助或建议都是非常感谢的。
1条答案
按热度按时间kxxlusnw1#
问题是我的像素着色器中的变量
PI
不是static
const
。显然,如果着色器中的变量没有声明为static
const
,那么它可能会被覆盖,这显然会导致像我经历的无法解释的行为。如果有人能更好地解释这一点,我仍然觉得我不明白100%。