【问题标题】:Trouble with Specular Lighting in OpenGLOpenGL中的镜面光照问题
【发布时间】:2015-01-31 00:37:48
【问题描述】:

我的镜面光照存在一些问题,我有环境光和漫反射,但我现在正在研究镜面光以尝试制作一个漂亮的模型。

我的 vertexShader 中有以下内容:

#version 330

layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 Normal;

out vec4 Colour0;

// Transforms
uniform mat4 gModelToWorldTransform;
uniform mat4 gWorldToViewToProjectionTransform;

// Ambient light parameters
uniform vec3 gAmbientLightIntensity;

// Directional light parameters
uniform vec3 gDirectionalLightIntensity;
uniform vec3 gDirectionalLightDirection;

// Material constants
uniform float gKa;
uniform float gKd;
uniform float gKs;
uniform float gKsStrength;

                                                                   
void main()
{  
    // Transform the vertex from local space to homogeneous clip space 
    vec4 vertexPositionInModelSpace = vec4(Position, 1);
    vec4 vertexInWorldSpace = gModelToWorldTransform * vertexPositionInModelSpace;
    vec4 vertexInHomogeneousClipSpace = gWorldToViewToProjectionTransform * vertexInWorldSpace;
    gl_Position = vertexInHomogeneousClipSpace;

    // Calculate the directional light intensity at the vertex
    // Find the normal in world space and normalise it
    vec3 normalInWorldSpace = (gModelToWorldTransform * vec4(Normal, 0.0)).xyz;
    normalInWorldSpace = normalize(normalInWorldSpace);

    // Calculate the ambient light intensity at the vertex
    // Ia = Ka * ambientLightIntensity
    vec4 ambientLightIntensity = gKa * vec4(gAmbientLightIntensity, 1.0);

    // Setup the light direction and normalise it
    vec3 lightDirection = normalize(-gDirectionalLightDirection);
    
    //lightDirection = normalize(gDirectionalLightDirection);
    // Id = kd * lightItensity * N.L
    // Calculate N.L
    float diffuseFactor = dot(normalInWorldSpace, lightDirection);
    diffuseFactor = clamp(diffuseFactor, 0.0, 1.0);

    // N.L * light source colour * intensity
    vec4 diffuseLightIntensity = gKd * vec4(gDirectionalLightIntensity, 1.0f) * diffuseFactor;

    vec3 lightReflect = normalize(reflect(gDirectionalLightDirection, Normal));

    //Calculate the specular light intensity at the vertex
    float specularFactor = dot(normalInWorldSpace, lightReflect);
    specularFactor = pow(specularFactor, gKsStrength);
    vec4 specularLightIntensity = gKs * vec4(gDirectionalLightIntensity, 1.0f) * specularFactor;
   
    // Final vertex colour is the product of the vertex colour
    // and the total light intensity at the vertex 

    vec4 colour = vec4(0.0, 1.0, 0.0, 1.0);
    Colour0 = colour * (ambientLightIntensity + diffuseLightIntensity + specularLightIntensity);
}

然后在我的 main.cpp 中,我有一些代码可以尝试让它们一起工作,镜面反射光肯定在做一些事情,只是,它并没有让模型看起来有光泽,它似乎将光强化到了我看不到任何细节。

我创建了以下变量:

// Lighting uniforms location

GLuint gAmbientLightIntensityLoc;
GLuint gDirectionalLightIntensityLoc;
GLuint gDirectionalLightDirectionLoc;
GLuint gSpecularLightIntensityLoc;

// Materials uniform location
GLuint gKaLoc;
GLuint gKdLoc;
GLuint gKsLoc;
GLuint gKsStrengthLoc;

然后我在主函数中调用的renderSceneCallBack() 函数中设置我的变量:

// Set the material properties
glUniform1f(gKaLoc, 0.2f); 
glUniform1f(gKdLoc, 0.9f);
glUniform1f(gKsLoc, 0.5f);
glUniform1f(gKsStrengthLoc, 0.5f);

然后我创建了一个initLights() 函数,我想处理所有的光照,这也在主函数中调用:

static void initLights()
{
    // Setup the ambient light
    vec3 ambientLightIntensity = vec3(0.2f, 0.2f, 0.2f);
    glUniform3fv(gAmbientLightIntensityLoc, 1, &ambientLightIntensity[0]);
    
    // Setup the direactional light
    vec3 directionalLightDirection = vec3(0.0f, 0.0f, -1.0f);
    normalize(directionalLightDirection);
    glUniform3fv(gDirectionalLightDirectionLoc, 1, &directionalLightDirection[0]);

    vec3 directionalLightIntensity = vec3(0.8f, 0.8f, 0.8f);
    glUniform3fv(gDirectionalLightIntensityLoc, 1, &directionalLightIntensity[0]);

    //Setup the specular Light
    vec3 specularLightIntensity = vec3(0.5f, 0.5f, 0.5f);
    glUniform3fv(gSpecularLightIntensityLoc, 1, &specularLightIntensity[0]);
}

任何人都可以看到我可能做错了什么,我可能有一些计算错误,我只是没有看到。环境/漫射照明都正常工作。这张照片说明了当前发生的情况,左侧是环境光,中间是漫反射,右侧是强度设置为 30 的镜面反射。

回答

我忘了把这个值传给主:

gKsStrengthLoc = glGetUniformLocation(shaderProgram, "gKsStrength");
    //assert(gDirectionalLightDirectionLoc != 0xFFFFFFFF);

现在使用所选答案一切正常

标签: c++ opengl lighting specular


【解决方案1】:

gKsStrength 的值看起来太小了:

glUniform1f(gKsStrengthLoc, 0.5f);

此值控制对象的光泽度,值越高,对象的光泽度越高。如果您查看着色器中的计算,这是有道理的:

specularFactor = pow(specularFactor, gKsStrength);

指数越大,数值下降的越快,这意味着镜面高光变得更窄。

典型值可能是 10.0f 表示中等光泽,30.0f 表示非常闪亮,甚至更高的材料表示非常闪亮。

使用 0.5f 的值,您可以获得非常宽的镜面反射“高光”。您的高光强度值也相当高(0.5),因此高光将覆盖大部分对象,并使大部分颜色饱和。

【讨论】:

  • 感谢您的输入,我玩过这个值,它似乎使对象更有活力而不是闪亮,这是正确的效果吗?我添加了一张照片来展示我的灯光
  • 我的错,我忘了主要参考 gksStrengthLoc,你是对的,先生,谢谢,我已经更新了我在问题中的错误
猜你喜欢
  • 2020-07-24
  • 2021-04-09
  • 2012-01-06
  • 1970-01-01
  • 1970-01-01
  • 2011-12-27
  • 2012-01-31
  • 1970-01-01
  • 2012-10-28
相关资源
最近更新 更多