如何修改PBR的阴影部分?
大家好!
我在Cesium中添加了3dtiles数据,我希望它渲染得更真实,所以我给它添加了pbr函数
**At some angles, the model looks bright:**
但是阴影部分看起来很奇怪,我的纹理模型上是替换为颜色
我尝试使用 clamp() 来修复结果,但它只会使模型看起来呈白色,
如何在阴影部分显示模型的纹理?
这是我的着色器代码:
vec3 lambertianDiffuse(vec3 diffuseColor)
{
return diffuseColor / czm_pi;
}
vec3 fresnelSchlick2(vec3 f0, vec3 f90, float VdotH)
{
return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);
}
float smithVisibilityG1(float NdotV, float roughness)
{
// this is the k value for direct lighting.
// for image based lighting it will be roughness^2 / 2
float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
return NdotV / (NdotV * (1.0 - k) + k);
}
float smithVisibilityGGX(float roughness, float NdotL, float NdotV)
{
return (
smithVisibilityG1(NdotL, roughness) *
smithVisibilityG1(NdotV, roughness)
);
}
float GGX(float roughness, float NdotH)
{
float roughnessSquared = roughness * roughness;
float f = (NdotH * roughnessSquared - NdotH) * NdotH + 1.0;
return roughnessSquared / (czm_pi * f * f);
}
/**
* @name czm_pbrlighting
* @glslFunction
* @param {vec3} positionEC The position of the fragment in eye coordinates
* @param {vec3} normalEC The surface normal in eye coordinates
* @param {vec3} lightDirectionEC Unit vector pointing to the light source in eye coordinates.
* @param {vec3} lightColorHdr radiance of the light source. This is a HDR value.
* @param {czm_pbrParameters} The computed PBR parameters.
* @return {vec3} The computed HDR color
*
* @example
* czm_pbrParameters pbrParameters = czm_pbrMetallicRoughnessMaterial(
* baseColor,
* metallic,
* roughness
* );
* vec3 color = czm_pbrlighting(
* positionEC,
* normalEC,
* lightDirectionEC,
* lightColorHdr,
* pbrParameters);
*/
vec3 czm_pbrLighting(
vec3 positionEC,
vec3 normalEC,
vec3 lightDirectionEC,
vec3 lightColorHdr,
czm_pbrParameters pbrParameters
)
{
vec3 v = -normalize(positionEC);
vec3 l = normalize(lightDirectionEC);
vec3 h = normalize(v + l);
vec3 n = normalEC;
float NdotL = clamp(dot(n, l), 0.001, 1.0);
float NdotV = abs(dot(n, v)) + 0.001;
float NdotH = clamp(dot(n, h), 0.0, 1.0);
float LdotH = clamp(dot(l, h), 0.0, 1.0);
float VdotH = clamp(dot(v, h), 0.0, 1.0);
vec3 f0 = pbrParameters.f0;
float reflectance = max(max(f0.r, f0.g), f0.b);
vec3 f90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0));
vec3 F = fresnelSchlick2(f0, f90, VdotH);
float alpha = pbrParameters.roughness;
float G = smithVisibilityGGX(alpha, NdotL, NdotV);
float D = GGX(alpha, NdotH);
vec3 specularContribution = F * G * D / (4.0 * NdotL * NdotV);
vec3 diffuseColor = pbrParameters.diffuseColor;
// F here represents the specular contribution
vec3 diffuseContribution = (1.0 - F) * lambertianDiffuse(diffuseColor);
// Lo = (diffuse + specular) * Li * NdotL
return (diffuseContribution + specularContribution) * NdotL * lightColorHdr;
}
**Thank you all.**
添加完整的着色器代码:
vec3 getPhongColor(vec3 positionToEyeEC, vec3 normalEC, vec3 color) {
czm_material material;
material.diffuse = color;
material.specular = 0.0;
material.shininess = 1.0;
material.normal = normalEC;
material.emission = vec3(0.0);
material.alpha = 1.0;
return clamp(czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC).rgb + 0.2, vec3(0.), vec3(1.));
}
vec3 computePbrLighting(czm_modelMaterial inputMaterial)
{
czm_pbrParameters pbrParameters;
pbrParameters.diffuseColor = inputMaterial.diffuse;
pbrParameters.f0 = inputMaterial.specular;
pbrParameters.roughness = inputMaterial.roughness;
vec3 lightColorHdr = czm_lightColorHdr;
vec3 color = inputMaterial.diffuse;
#ifdef HAS_NORMALS
color = czm_pbrLighting(
v_positionEC,
inputMaterial.normalEC,
czm_lightDirectionEC,
lightColorHdr,
pbrParameters
);
#endif
// color *= inputMaterial.occlusion;
// color += inputMaterial.emissive;
color = mix(color, inputMaterial.diffuse, 0.0995);
// In HDR mode, the frame buffer is in linear color space. The
// post-processing stages (see PostProcessStageCollection) will handle
// tonemapping. However, if HDR is not enabled, we must tonemap else large
// values may be clamped to 1.0
#ifndef HDR
color = czm_acesTonemapping(color);
#endif
return color * 1.2;
}
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
vec3 positionMC = fsInput.attributes.positionMC;
vec3 normalEC = fsInput.attributes.normalEC;
vec3 positionToEyeEC = -fsInput.attributes.positionEC;
vec2 st = fsInput.attributes.texCoord_0;
float width = floor(fsInput.attributes.buildinglength + 0.5);
float height = floor(fsInput.attributes.buildingheight + 0.5);
float buildingType = floor(fsInput.attributes.buildingtype + .5);
bool isTop = dot(vec3(0.0, 0.0, 1.0), v_normalMC) > 0.999;
bool isBottom = dot(vec3(0.0, 0.0, -1.0), v_normalMC) > 0.999;
vec3 color = material.diffuse;
bool isOutHeatZone = color == vec3(0.);
bool isHighlight = color == vec3(0., 0., 1.);
st = vec2(1. - st.x, 1. - st.y);
if(isHighlight) {
if (isTop) {
material.diffuse = vec3(.82, .8, .22);
} else {
material.diffuse = getPhongColor(positionToEyeEC, normalEC, vec3(.87, .82, .04));
}
} else if(isOutHeatZone) {
const float size = 9.;
float s = size;
for(int i = int(size); i > 3; i--) {
if(mod(height, float(i)) == 0.) {
break;
} else {
s--;
}
}
float textureX = mod(st.x * width, s) / s;
float textureY = mod(st.y * height, s) / s;
if (isTop) {
if (buildingType == 1060102.) {
material.diffuse = vec3(0.3137254901960784, 0.3607843137254902, 0.3686274509803922);
}else if (buildingType == 1060103.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060201.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060202.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060203.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060204.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060101.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060501.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060502.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else {
material.diffuse = vec3(0.8509803921568627, 0.8509803921568627, 0.8509803921568627);
}
} else {
if (buildingType == 1060102.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 1.) / 2.)).rgb;
} else if (buildingType == 1060103.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 1.) / 3., (textureY + 1.) / 2.)).rgb;
} else if (buildingType == 1060201.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060202.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060203.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060204.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060101.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 1.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060501.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 2.) / 3., (textureY + 1.) / 2.)).rgb;
} else if (buildingType == 1060502.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 2.) / 3., (textureY + 1.) / 2.)).rgb;
} else {
material.diffuse = texture2D(u_texture, vec2((textureX + 2.) / 3., (textureY + 0.) / 2.)).rgb;
}
}
material.diffuse = computePbrLighting(material);
} else {
if (!isTop) {
float deep = clamp(st.y + .5, .5, 1.) * 1.5;
vec3 phongColor = getPhongColor(positionToEyeEC, normalEC, color * deep);
material.diffuse = mix(phongColor, color * .7, .3);
}
}
}"
Hello everyone!
I added 3dtiles data in Cesium, I want it to render more realistic, so I added a pbr function to it
**At some angles, the model looks bright:**
But the shaded part looks strange,my texture on the model was replaced with a color
I've tried to clamp() to fix the results, but it just makes the model look white,
How can I display the model's texture in the shaded part?
This is my shader code:
vec3 lambertianDiffuse(vec3 diffuseColor)
{
return diffuseColor / czm_pi;
}
vec3 fresnelSchlick2(vec3 f0, vec3 f90, float VdotH)
{
return f0 + (f90 - f0) * pow(clamp(1.0 - VdotH, 0.0, 1.0), 5.0);
}
float smithVisibilityG1(float NdotV, float roughness)
{
// this is the k value for direct lighting.
// for image based lighting it will be roughness^2 / 2
float k = (roughness + 1.0) * (roughness + 1.0) / 8.0;
return NdotV / (NdotV * (1.0 - k) + k);
}
float smithVisibilityGGX(float roughness, float NdotL, float NdotV)
{
return (
smithVisibilityG1(NdotL, roughness) *
smithVisibilityG1(NdotV, roughness)
);
}
float GGX(float roughness, float NdotH)
{
float roughnessSquared = roughness * roughness;
float f = (NdotH * roughnessSquared - NdotH) * NdotH + 1.0;
return roughnessSquared / (czm_pi * f * f);
}
/**
* @name czm_pbrlighting
* @glslFunction
* @param {vec3} positionEC The position of the fragment in eye coordinates
* @param {vec3} normalEC The surface normal in eye coordinates
* @param {vec3} lightDirectionEC Unit vector pointing to the light source in eye coordinates.
* @param {vec3} lightColorHdr radiance of the light source. This is a HDR value.
* @param {czm_pbrParameters} The computed PBR parameters.
* @return {vec3} The computed HDR color
*
* @example
* czm_pbrParameters pbrParameters = czm_pbrMetallicRoughnessMaterial(
* baseColor,
* metallic,
* roughness
* );
* vec3 color = czm_pbrlighting(
* positionEC,
* normalEC,
* lightDirectionEC,
* lightColorHdr,
* pbrParameters);
*/
vec3 czm_pbrLighting(
vec3 positionEC,
vec3 normalEC,
vec3 lightDirectionEC,
vec3 lightColorHdr,
czm_pbrParameters pbrParameters
)
{
vec3 v = -normalize(positionEC);
vec3 l = normalize(lightDirectionEC);
vec3 h = normalize(v + l);
vec3 n = normalEC;
float NdotL = clamp(dot(n, l), 0.001, 1.0);
float NdotV = abs(dot(n, v)) + 0.001;
float NdotH = clamp(dot(n, h), 0.0, 1.0);
float LdotH = clamp(dot(l, h), 0.0, 1.0);
float VdotH = clamp(dot(v, h), 0.0, 1.0);
vec3 f0 = pbrParameters.f0;
float reflectance = max(max(f0.r, f0.g), f0.b);
vec3 f90 = vec3(clamp(reflectance * 25.0, 0.0, 1.0));
vec3 F = fresnelSchlick2(f0, f90, VdotH);
float alpha = pbrParameters.roughness;
float G = smithVisibilityGGX(alpha, NdotL, NdotV);
float D = GGX(alpha, NdotH);
vec3 specularContribution = F * G * D / (4.0 * NdotL * NdotV);
vec3 diffuseColor = pbrParameters.diffuseColor;
// F here represents the specular contribution
vec3 diffuseContribution = (1.0 - F) * lambertianDiffuse(diffuseColor);
// Lo = (diffuse + specular) * Li * NdotL
return (diffuseContribution + specularContribution) * NdotL * lightColorHdr;
}
**Thank you all.**
Add the complete shader code:
vec3 getPhongColor(vec3 positionToEyeEC, vec3 normalEC, vec3 color) {
czm_material material;
material.diffuse = color;
material.specular = 0.0;
material.shininess = 1.0;
material.normal = normalEC;
material.emission = vec3(0.0);
material.alpha = 1.0;
return clamp(czm_phong(normalize(positionToEyeEC), material, czm_lightDirectionEC).rgb + 0.2, vec3(0.), vec3(1.));
}
vec3 computePbrLighting(czm_modelMaterial inputMaterial)
{
czm_pbrParameters pbrParameters;
pbrParameters.diffuseColor = inputMaterial.diffuse;
pbrParameters.f0 = inputMaterial.specular;
pbrParameters.roughness = inputMaterial.roughness;
vec3 lightColorHdr = czm_lightColorHdr;
vec3 color = inputMaterial.diffuse;
#ifdef HAS_NORMALS
color = czm_pbrLighting(
v_positionEC,
inputMaterial.normalEC,
czm_lightDirectionEC,
lightColorHdr,
pbrParameters
);
#endif
// color *= inputMaterial.occlusion;
// color += inputMaterial.emissive;
color = mix(color, inputMaterial.diffuse, 0.0995);
// In HDR mode, the frame buffer is in linear color space. The
// post-processing stages (see PostProcessStageCollection) will handle
// tonemapping. However, if HDR is not enabled, we must tonemap else large
// values may be clamped to 1.0
#ifndef HDR
color = czm_acesTonemapping(color);
#endif
return color * 1.2;
}
void fragmentMain(FragmentInput fsInput, inout czm_modelMaterial material) {
vec3 positionMC = fsInput.attributes.positionMC;
vec3 normalEC = fsInput.attributes.normalEC;
vec3 positionToEyeEC = -fsInput.attributes.positionEC;
vec2 st = fsInput.attributes.texCoord_0;
float width = floor(fsInput.attributes.buildinglength + 0.5);
float height = floor(fsInput.attributes.buildingheight + 0.5);
float buildingType = floor(fsInput.attributes.buildingtype + .5);
bool isTop = dot(vec3(0.0, 0.0, 1.0), v_normalMC) > 0.999;
bool isBottom = dot(vec3(0.0, 0.0, -1.0), v_normalMC) > 0.999;
vec3 color = material.diffuse;
bool isOutHeatZone = color == vec3(0.);
bool isHighlight = color == vec3(0., 0., 1.);
st = vec2(1. - st.x, 1. - st.y);
if(isHighlight) {
if (isTop) {
material.diffuse = vec3(.82, .8, .22);
} else {
material.diffuse = getPhongColor(positionToEyeEC, normalEC, vec3(.87, .82, .04));
}
} else if(isOutHeatZone) {
const float size = 9.;
float s = size;
for(int i = int(size); i > 3; i--) {
if(mod(height, float(i)) == 0.) {
break;
} else {
s--;
}
}
float textureX = mod(st.x * width, s) / s;
float textureY = mod(st.y * height, s) / s;
if (isTop) {
if (buildingType == 1060102.) {
material.diffuse = vec3(0.3137254901960784, 0.3607843137254902, 0.3686274509803922);
}else if (buildingType == 1060103.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060201.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060202.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060203.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060204.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060101.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060501.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else if (buildingType == 1060502.) {
material.diffuse = vec3(0.6431372549019608, 0.6431372549019608, 0.6431372549019608);
}else {
material.diffuse = vec3(0.8509803921568627, 0.8509803921568627, 0.8509803921568627);
}
} else {
if (buildingType == 1060102.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 1.) / 2.)).rgb;
} else if (buildingType == 1060103.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 1.) / 3., (textureY + 1.) / 2.)).rgb;
} else if (buildingType == 1060201.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060202.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060203.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060204.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 0.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060101.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 1.) / 3., (textureY + 0.) / 2.)).rgb;
} else if (buildingType == 1060501.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 2.) / 3., (textureY + 1.) / 2.)).rgb;
} else if (buildingType == 1060502.) {
material.diffuse = texture2D(u_texture, vec2((textureX + 2.) / 3., (textureY + 1.) / 2.)).rgb;
} else {
material.diffuse = texture2D(u_texture, vec2((textureX + 2.) / 3., (textureY + 0.) / 2.)).rgb;
}
}
material.diffuse = computePbrLighting(material);
} else {
if (!isTop) {
float deep = clamp(st.y + .5, .5, 1.) * 1.5;
vec3 phongColor = getPhongColor(positionToEyeEC, normalEC, color * deep);
material.diffuse = mix(phongColor, color * .7, .3);
}
}
}"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论