在我的地形的某些部分,Phong照明有时太亮(OpenGL)

在我的地形的某些部分,Phong照明有时太亮(OpenGL),opengl,glsl,shader,light,phong,Opengl,Glsl,Shader,Light,Phong,我使用三角带和高度图制作了一个山区地形,并使用3D平面投影进行纹理处理。对于3D平面投影,我遵循了下面链接的第1.5节。 这是Phong Lighting之前的样子。Unitl纹理,还可以 这就是Phong Lighting的外观。请注意,我假设了平行光,因此我假设灯光方向朝向-y轴方向。我将其设置为shader.setVec3(“light.direction”,0.0f,-0.1f,0.0f) 地形的某些部分突然变得更亮,好像光只在这些部分变强 我检查了法向量是否正确。所以我用几何体着

我使用三角带和高度图制作了一个山区地形,并使用3D平面投影进行纹理处理。对于3D平面投影,我遵循了下面链接的第1.5节。

这是Phong Lighting之前的样子。Unitl纹理,还可以

这就是Phong Lighting的外观。请注意,我假设了平行光,因此我假设灯光方向朝向-y轴方向。我将其设置为
shader.setVec3(“light.direction”,0.0f,-0.1f,0.0f)

地形的某些部分突然变得更亮,好像光只在这些部分变强

我检查了法向量是否正确。所以我用几何体着色器将它们可视化。结果如下

如你所见,法向量实际上是正确的。所以我的着色器程序一定出了问题。这是密码。首先,顶点着色器

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aNormal;

uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;

float scale = 0.5;

out vec2 TexX;
out vec2 TexY;
out vec2 TexZ;
out vec3 blend_weights;
out vec3 FragPos;
out vec3 wNormal;

void main()
{
    FragPos = vec3(model * vec4(aPos, 1.0));    
    blend_weights = abs(aNormal.xyz);
    blend_weights = (blend_weights - 0.2) * 0.7;
    blend_weights = max(blend_weights, 0);
    blend_weights /= (blend_weights.x + blend_weights.y + blend_weights.z);

    TexX = aPos.yz * scale;
    TexY = aPos.zx * scale; 
    TexZ = aPos.xy * scale;

    wNormal = mat3(transpose(inverse(model))) * aNormal;

    gl_Position = projection * view * vec4(FragPos, 1.0);
}
这是我的片段着色器

#version 330 core
out vec4 FragColor;

struct Material{

    //aka terrainTexture;
    sampler2D diffuse;
    sampler2D specular;
    float shininess;
};

struct Light {
    // Direction has to be in world coordinates.
    vec3 direction;
    vec3 ambient;
    vec3 diffuse;
    vec3 specular;
};

uniform Light light;
uniform Material material;
uniform vec3 viewPos;

in vec3 FragPos;    //world Coordinate!
in vec2 TexX;
in vec2 TexY;
in vec2 TexZ;

in vec3 wNormal;

in vec3 blend_weights;

void main()
{
    vec4 ColorNoLighting = texture(material.diffuse, TexX)*blend_weights.x + texture(material.diffuse, TexY)*blend_weights.y + texture(material.diffuse, TexZ)*blend_weights.z;

    vec3 ambient = light.ambient * ColorNoLighting.xyz; 

    vec3 norm = normalize(wNormal);
    vec3 lightDir = normalize(-light.direction);
    float diff = max(dot(norm, lightDir), 0.0);
    vec3 diffuse = light.diffuse * diff * ColorNoLighting.xyz;

    vec3 viewDir = normalize(viewPos - FragPos);
    vec3 reflectDir = reflect(-lightDir, norm);
    float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
    vec3 specular = light.specular * spec * ColorNoLighting.xyz;

    vec3 result = ambient + diffuse + specular;
    FragColor = vec4(result, 1.0);
}
最后,这是我设置所有制服的方式

shader.use();
shader.setInt("material.diffuse", 0);
shader.setInt("material.specular", 1);
shader.setVec3("light.direction", 0.0f, -0.1f, 0.0f);
shader.setVec3("viewPos", camera.Position);
shader.setVec3("light.ambient", 0.2f, 0.2f, 0.2f);
shader.setVec3("light.diffuse", 0.5f, 0.5f, 0.5f);
shader.setVec3("light.specular", 1.0f, 1.0f, 1.0f);
shader.setFloat("material.shininess", 32.0f);
shader.setMat4("model", model);
shader.setMat4("view", view);
shader.setMat4("projection", projection);
我不明白为什么我的某些地方在打了电话后突然变得如此明亮。任何帮助都将不胜感激。提前谢谢

与Phong镜面反射高光相比,灯光的漫反射分量较弱

在着色器代码中,漫反射组件的强度由参数
light.diffuse设置:

float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = light.diffuse * diff * ColorNoLighting.xyz;
镜面反射组件的强度及其大小分别由
灯光、镜面反射
材料、光泽度
设置:

float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = light.specular * spec * ColorNoLighting.xyz;
请注意,如果“光泽度”参数减小,则镜面反射高光的大小会增加,但会变得更平滑

更改参数以解决您的问题

e、 g

请参见示例,该示例演示了参数的效果:

(函数loadscene(){
var滑块刻度=100.0
var-gl;
var帆布;
var-vp_大小;
var-prograw;
var bufTorus={};
函数渲染(deltaMS){
var ambient=document.getElementById(“ambient”).value/sliderScale;
var diffuse=document.getElementById(“diffuse”).value/sliderScale;
var specular=document.getElementById(“specular”).value/sliderScale;
var shininess=Math.max(1,document.getElementById(“shininess”).value/2);
document.getElementById(“环境值”).innerHTML=ambient;
document.getElementById(“漫反射值”).innerHTML=diffuse;
document.getElementById(“specular_val”).innerHTML=specular;
document.getElementById(“shininess_val”).innerHTML=shininess;
Camera.create();
Camera.vp=[canvas.width,canvas.height];
总图视口(0,0,canvas.width,canvas.height);
总帐启用(总帐深度测试);
gl.clearColor(0.0,0.0,0.0,1.0);
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
//设置绘图着色器
着色器程序。使用(progDraw);
SetUniformMat44(progDraw,“u_projectionMat44”,Camera.Perspective());
SetUniformMat44(progDraw,“u_viewMat44”,Camera.LookAt());
SetUniform3f(progDraw,“u_lightDir”[-1.0,-0.5,-2.0])
着色器程序SetUniformFloat(progDraw,“u_环境”,环境)
着色器程序。SetUniformFloat(progDraw,“u_漫反射”,漫反射)
着色器程序。SetUniformFloat(progDraw,“u_镜面反射”,镜面反射)
ShaderProgram.SetUniformFloat(progDraw,“亮度”,亮度)
var modelMat=IdentityMat44()
modelMat=旋转轴(modelMat,CalcAng(deltaMS,13.0),0);
modelMat=旋转轴(modelMat,CalcAng(deltaMS,17.0),1);
着色器程序。SetUniformMat44(progDraw,“u_modelMat44”,modelMat);
//画场景
顶点缓冲区绘制(bufTorus);
请求动画帧(渲染);
}
函数initScene(){
document.getElementById(“环境”).value=0.2*滑块刻度;
document.getElementById(“漫反射”).value=0.75*sliderScale;
document.getElementById(“镜面反射”).value=0.75*sliderScale;
document.getElementById(“光泽”).value=20.0;
canvas=document.getElementById(“phong canvas”);
vp_size=[canvas.width,canvas.height];
gl=canvas.getContext(“实验性webgl”);
如果(!gl)
返回;
progDraw=ShaderProgram.Create(
[{来源:“绘制着色器vs”,阶段:gl.VERTEX_shader},
{来源:“绘制着色器fs”,阶段:gl.FRAGMENT_shader}
],
[“u_projectionMat44”、“u_viewMat44”、“u_modelMat44”,
“u_lightDir”、“u_ambient”、“u_diffuse”、“u_镜面反射”、“u_shininess”];
progDraw.inPos=gl.getAttribLocation(progDraw,“inPos”);
progDraw.inNV=gl.getAttribLocation(progDraw,“inNV”);
progDraw.inCol=gl.getAttribLocation(progDraw,“inCol”);
如果(progDraw==0)
返回;
//创建圆环体
变量环尺寸=32,管尺寸=32;
var rad_环=1.0;
var rad_管=0.5;
var torus_pts=[];
var torus_nv=[];
var torus_col=[];
var torus_inx=[];
var col=[1,0.5,0.0];
对于(变量i_c=0;i_c<周长;++i_c){
变量中心=[
Math.cos(2*Math.PI*i_c/circu size),
Math.sin(2*Math.PI*i_c/circu size)]
对于(变量i_t=0;i_tshader.setVec3("light.diffuse", 1.0f, 1.0f, 1.0f);
shader.setVec3("light.specular", 0.5f, 0.5f, 0.5f);
shader.setFloat("material.shininess", 10.0f);