认为我的场景没有正确照明吗? opengl

时间:2019-01-22 18:08:29

标签: c++ opengl glsl lighting

我正在尝试在我的顶点着色器中实现照明,但是,顶点的颜色似乎并没有太大变化。

#version 330

顶点属性的结构化布局

layout (location = 0 ) in vec3 vertex_position;

layout (location = 1 ) in vec3 vertex_color;

layout (location = 2 ) in vec3 vertex_normal;

///统一变量

uniform mat4 ModelMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat4 NormalMatrix;

uniform vec3 AmbientFinal;   

/// struct处理灯光信息和材质信息

 struct lightInfo
{
    vec3 LightPosition;
    vec3 ambientLightInt;
    vec3 diffuseLightInt;
    vec3 SpecularLightInt;
};

uniform lightInfo lights;

struct MaterialInfo
{
    vec3 ka;
    vec3 kd;
    vec3 ks;
    float Shineness;
};

uniform MaterialInfo material;

out vec3 colour;

主要照明计算

void main()
{
  ///light position in eye coordinates
  vec4 lighteye =   ViewMatrix * ModelMatrix * vec4(lights.LightPosition, 1.0f);         
  vec3 tnorm = normalize(mat3(NormalMatrix) *  vertex_normal);

///在眼球中的位置

vec4 eyeCoords = ViewMatrix*ModelMatrix* vec4(vertex_position, 1.f);

   vec3 s = normalize(vec3(lighteye - eyeCoords));
   vec3 v = normalize(-eyeCoords.xyz);
   vec3 r = reflect(-s, tnorm);
   vec3 ambient = material.ka * lights.ambientLightInt;
   float sdotn = max(dot(s, tnorm),0.0);
   vec3 diffuse = lights.diffuseLightInt * material.kd * sdotn;
   vec3 spec = vec3(0.0);
   if(sdotn > 0)
   spec = lights.SpecularLightInt * material.ks * pow (max(dot(r,v), 0.0), material.Shineness);


  gl_Position =  ProjectionMatrix *ViewMatrix*ModelMatrix* vec4(vertex_position, 1.f);
  colour =  (diffuse + ambient + spec)  + vertex_color;
}        

生产的输出

output from running program

没有光照计算的输出

output without lighting

这些是变量

///lights and Mats
lightInfo lights;
lights.LightPosition =   glm::vec3(0.f, 0.f,  2.f);
lights.ambientLightInt = glm::vec3(0.1f, 0.1f, 0.1f);
lights.diffuseLightInt = glm::vec3(1.f);
lights.SpecularLightInt = glm::vec3(1.f);

MaterialInfo mat;
mat.ka = glm::vec3(0.1f, 0.1f, 0.1f);
mat.kd = glm::vec3(0.5f, 0.5f, 0.5f);
mat.ks = glm::vec3(0.5f, 0.5f, 0.5f);
mat.Shineness = 30.f;

也许我对照明的理解是错误的?我不明白为什么3d对象没有真正受到光照计算的影响

Hard coded the term

1 个答案:

答案 0 :(得分:0)

通常您的程序可以正常工作。

但是普通矩阵应为mat3类型。共有的光照位置是世界空间中的一个位置,并且仅可以通过视图矩阵进行转换(如果光照计算是在视图空间中完成的话):

uniform mat3 NormalMatrix;

// [...]

vond main()
{
    vec4 lighteye =   ViewMatrix * vec4(lights.LightPosition, 1.0f);
    vec3 tnorm = normalize(NormalMatrix *  vertex_normal);

    // [...]
}

确保视图位置不在矩形上。视图位置必须在矩形的前面:

例如

glm::mat4 view = glm::lookAt(
    glm::vec3(0.0f, 0.0f, 0.5f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));

我使用以下程序测试您的代码并生成小型动画(我使用了glewglmglfw库):

顶点着色器:

#version 330

layout (location = 0 ) in vec3 vertex_position;
layout (location = 1 ) in vec3 vertex_color;
layout (location = 2 ) in vec3 vertex_normal;

uniform mat4 ModelMatrix;
uniform mat4 ProjectionMatrix;
uniform mat4 ViewMatrix;
uniform mat3 NormalMatrix;

uniform vec3 AmbientFinal;  

struct lightInfo
{
    vec3 LightPosition;
    vec3 ambientLightInt;
    vec3 diffuseLightInt;
    vec3 SpecularLightInt;
};

uniform lightInfo lights;

struct MaterialInfo
{
    vec3 ka;
    vec3 kd;
    vec3 ks;
    float Shineness;
};

uniform MaterialInfo material;

out vec3 colour;

void main()
{
    ///light position in eye coordinates
    vec4 lighteye =   ViewMatrix * vec4(lights.LightPosition, 1.0f);         
    vec3 tnorm = normalize(NormalMatrix *  vertex_normal);

    vec4 eyeCoords = ViewMatrix*ModelMatrix* vec4(vertex_position, 1.f);

    vec3 s = normalize(vec3(lighteye - eyeCoords));
    vec3 v = normalize(-eyeCoords.xyz);
    vec3 r = reflect(-s, tnorm);
    vec3 ambient = material.ka * lights.ambientLightInt;
    float sdotn = max(dot(s, tnorm),0.0);
    vec3 diffuse = lights.diffuseLightInt * material.kd * sdotn;
    vec3 spec = vec3(0.0);
    if(sdotn > 0)
    spec = lights.SpecularLightInt * material.ks * pow (max(dot(r,v), 0.0), material.Shineness);

    gl_Position =  ProjectionMatrix *ViewMatrix*ModelMatrix* vec4(vertex_position, 1.f);
    colour =  (diffuse + ambient + spec)  + vertex_color;
} 

片段着色器:

#version 330

in vec3 colour;
out vec4 fragColor;

void main()
{
    fragColor = vec4(colour, 1.0);
}

main程序:

int main(void)
{
    if ( glfwInit() == 0 )
        return 0;
    GLFWwindow *wnd = glfwCreateWindow( 800, 600, "OGL window", nullptr, nullptr );
    if ( wnd == nullptr )
        return 0;
    glfwMakeContextCurrent(wnd);
    glewExperimental = true;
    if ( glewInit() != GLEW_OK )
        return 0;

    GLuint program    = CreateProgram( sh_vert, sh_frag );
    GLint  loc_normal = glGetUniformLocation(program, "NormalMatrix");
    GLint  loc_model  = glGetUniformLocation(program, "ModelMatrix");
    GLint  loc_view   = glGetUniformLocation(program, "ViewMatrix");
    GLint  loc_proj   = glGetUniformLocation(program, "ProjectionMatrix");
    GLint  loc_l_lp   = glGetUniformLocation(program, "lights.LightPosition");
    GLint  loc_l_al   = glGetUniformLocation(program, "lights.ambientLightInt");
    GLint  loc_l_dl   = glGetUniformLocation(program, "lights.diffuseLightInt");
    GLint  loc_l_sl   = glGetUniformLocation(program, "lights.SpecularLightInt");
    GLint  loc_m_ka   = glGetUniformLocation(program, "material.ka");
    GLint  loc_m_kd   = glGetUniformLocation(program, "material.kd");
    GLint  loc_m_ks   = glGetUniformLocation(program, "material.ks");
    GLint  loc_m_sh   = glGetUniformLocation(program, "material.Shineness");

    glUseProgram(program);

    glm::mat4 proj(1.0f);
    glm::mat4 view = glm::lookAt(glm::vec3(0.0f, 0.0f, 0.5f), glm::vec3(0.0f, 0.0f, 0.0f), glm::vec3(0.0f, 1.0f, 0.0f));
    glm::mat4 model(1.0f);
    glm::mat3 normal = glm::transpose(glm::inverse(glm::mat3(view * model)));

    glUniformMatrix3fv(loc_normal, 1, GL_FALSE, glm::value_ptr(normal) );
    glUniformMatrix4fv(loc_model,  1, GL_FALSE, glm::value_ptr(model) );
    glUniformMatrix4fv(loc_view,   1, GL_FALSE, glm::value_ptr(view) );
    glUniformMatrix4fv(loc_proj,   1, GL_FALSE, glm::value_ptr(proj) );
    glUniform3f(loc_l_lp, 0.f, 0.f, 1.f);
    glUniform3f(loc_l_al, 0.1f, 0.1f, 0.1f);
    glUniform3f(loc_l_dl, 1.f, 1.f, 1.f);
    glUniform3f(loc_l_sl, 1.f, 1.f, 1.f);
    glUniform3f(loc_m_ka, 0.1f, 0.1f, 0.1f);
    glUniform3f(loc_m_kd, 0.7f, 0.7f, 0.7f);
    glUniform3f(loc_m_ks, 1.0f, 1.0f, 1.0f);
    glUniform1f(loc_m_sh, 30.f);

    const std::vector<float> varray
    { 
      -0.5f, -0.5f,    1.0f, 0.0f, 0.0f, 1.0f,    0.0f, 0.0f, 1.0f, 
       0.5f, -0.5f,    1.0f, 0.0f, 0.0f, 1.0f,    0.0f, 0.0f, 1.0f, 
       0.5f,  0.5f,    1.0f, 0.0f, 0.0f, 1.0f,    0.0f, 0.0f, 1.0f, 
      -0.5f,  0.5f,    1.0f, 0.0f, 0.0f, 1.0f,    0.0f, 0.0f, 1.0f
    };
    const std::vector<unsigned int> iarray{ 0, 1, 2, 0, 2, 3 };

    GLuint bo[2];
    glGenBuffers(1, bo);
    glBindBuffer(GL_ARRAY_BUFFER, bo[0]);
    glBufferData(GL_ARRAY_BUFFER, varray.size()*sizeof(*varray.data()), varray.data(), GL_STATIC_DRAW);

    GLuint vao;
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 9*sizeof(*varray.data()), 0);
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 9*sizeof(*varray.data()), (void*)(2*sizeof(*varray.data())));
    glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE, 9*sizeof(*varray.data()), (void*)(6*sizeof(*varray.data())));
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, bo[1]);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, iarray.size()*sizeof(*iarray.data()), iarray.data(), GL_STATIC_DRAW);

    float ang = 0.0;
    while (!glfwWindowShouldClose(wnd))
    {
        int vpSize[2];
        glfwGetFramebufferSize( wnd, &vpSize[0], &vpSize[1] );

        glViewport( 0, 0, vpSize[0], vpSize[1] );
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

        float sa = sin( ang );
        ang += 0.05f;
        glUniform3f(loc_l_lp, 0.5f*sa, 0.5f*sa, 0.5f);

        glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);

        glfwSwapBuffers(wnd);
        glfwPollEvents();
    }

    glfwTerminate();
    return 0;
}