简体   繁体   English

OpenGL 的漫射照明问题

[英]Problem with diffuse lighting with OpenGL

My diffuse lighting doesn't seem to be working properly.我的漫射照明似乎无法正常工作。

Fragment Shader:片段着色器:

#version 330 core

out vec4 gl_FragColor;

in vec4 vertexColor;
in vec2 texelCoord;
in vec3 Normal;

struct DirectionalLight
{
    vec3 color;
    float ambientIntensity;
    vec3 direction;
    float diffuseIntensity;
};

uniform sampler2D textureSampler;
uniform DirectionalLight directionalLight;

void main()
{
    vec4 ambientColor = vec4(directionalLight.color, 1.0f) * directionalLight.ambientIntensity;
    
    float diffuseFactor = max(dot(normalize(Normal), normalize(directionalLight.direction)), 0.0f);
    vec4 diffuseColor = vec4(directionalLight.color, 1.0f) * directionalLight.diffuseIntensity * diffuseFactor;
    
    gl_FragColor = texture(textureSampler, texelCoord) * (ambientColor + diffuseColor);
}

Vertex Shader:顶点着色器:

#version 330 core

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in vec3 normal;

out vec4 vertexColor;
out vec2 texelCoord;
out vec3 Normal;

uniform mat4 transformation;
uniform mat4 projection;
uniform mat4 view;

void main()
{
    gl_Position = projection * view * transformation * vec4( position, 1.0f );
    vertexColor = vec4(clamp(position, 0.0f, 1.0f), 1.0f);
    
    texelCoord = texCoord;
    Normal = mat3(transpose(inverse(transformation))) * normal;
}

How I create Meshes:我如何创建网格:

void CalcAverageNormals( unsigned int* indices , unsigned int indicesCount , float* vertices , unsigned int verticesCount , unsigned int vertexLength , unsigned int normalOffset )
{
    for ( int i = 0; i < indicesCount; i += 3 )
    {
        unsigned int v1 = indices[i] * vertexLength;
        unsigned int v2 = indices[ i + 1 ] * vertexLength;
        unsigned int v3 = indices[ i + 2 ] * vertexLength;

        glm::vec3 line1( vertices[ v2 ] - vertices[ v1 ] , vertices[ v2 + 1 ] - vertices[ v1 + 1 ] , vertices[ v2 + 2 ] - vertices[ v1 + 2 ] );
        glm::vec3 line2( vertices[ v3 ] - vertices[ v1 ] , vertices[ v3 + 1 ] - vertices[ v1 + 1 ] , vertices[ v3 + 2 ] - vertices[ v1 + 2 ] );
        glm::vec3 normal = glm::normalize( glm::cross( line1 , line2 ) );

        v1 += normalOffset;
        v2 += normalOffset;
        v3 += normalOffset;

        vertices[ v1 ] += normal.x; vertices[ v1 + 1 ] += normal.y; vertices[ v1 + 2 ] += normal.z;
        vertices[ v2 ] += normal.x; vertices[ v2 + 1 ] += normal.y; vertices[ v2 + 2 ] += normal.z;
        vertices[ v3 ] += normal.x; vertices[ v3 + 1 ] += normal.y; vertices[ v3 + 2 ] += normal.z;
    }

    for ( int j = 0; j < verticesCount / vertexLength; j++ )
    {
        unsigned int offset = j * vertexLength + normalOffset;
        glm::vec3 normalVertex( vertices[ offset ] , vertices[ offset + 1 ] , vertices[ offset + 2 ] );
        normalVertex = glm::normalize( normalVertex );

        vertices[ offset ] = normalVertex.x;
        vertices[ offset + 1 ] = normalVertex.y;
        vertices[ offset + 2 ] = normalVertex.z;
    }
}

void CreateTriangle() {

    float vertices[] {
       -0.5f,-0.5f, 0.0f,  0.0f, 0.0f,  0.0f, 0.0f, 0.0f, // Left
        0.5f,-0.5f, 0.0f,  1.0f, 0.0f,  0.0f, 0.0f, 0.0f, // Right
        0.0f, 0.5f, 0.0f,  0.5f, 1.0f,  0.0f, 0.0f, 0.0f, // Top
        0.0f,-0.5f, 0.5f,  0.5f, 0.0f,  0.0f, 0.0f, 0.0f  // Back Z
    };

    unsigned int indices[]{
        0, 1, 2, // Front
        3, 2, 1, // Right
        3, 2, 0, // Left
        3, 0, 1  // Bottom
    };

    CalcAverageNormals( indices , 12 , vertices , 32 , 8 , 5 );

    for ( int i = 0; i < 1; i++ )
    {
        Mesh* obj = new Mesh();

        obj->CreateMesh( vertices , 32 , indices , 12 );
        meshlist.push_back( obj );
    }

}

CreateMesh()创建网格()

void Mesh::CreateMesh( float* vertices , unsigned int numVertices , unsigned int* indices , unsigned int numIndices )
    {
        uIndices = numIndices;
    
        glGenVertexArrays( 1 , &vao );
        glBindVertexArray( vao );
    
        /*Create Buffers*/
        glGenBuffers( 1 , &ibo );
        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , ibo );
        glBufferData( GL_ELEMENT_ARRAY_BUFFER , numIndices * sizeof(unsigned) , indices , GL_STATIC_DRAW );
    
        glGenBuffers( 1 , &vbo );
        glBindBuffer( GL_ARRAY_BUFFER , vbo );
        glBufferData( GL_ARRAY_BUFFER , numVertices * sizeof(float) , vertices , GL_STATIC_DRAW );
    
        glVertexAttribPointer( 0 , 3 , GL_FLOAT , GL_FALSE , sizeof( vertices[ 0 ] ) * 8 , 0 );
        glEnableVertexAttribArray( 0 );
        glVertexAttribPointer( 1 , 2 , GL_FLOAT , GL_FALSE , sizeof( vertices[ 0 ] ) * 8 , ( void* )( sizeof( vertices[ 0 ] ) * 3 ) );
        glEnableVertexAttribArray( 1 );
        glVertexAttribPointer( 2 , 3 , GL_FLOAT , GL_FALSE , sizeof( vertices[ 0 ] ) * 8 , ( void* )( sizeof( vertices[ 0 ] ) * 5 ) );
        glEnableVertexAttribArray( 2 );
    
        /*Unbind Objects*/
        glBindBuffer( GL_ARRAY_BUFFER , 0 );
    
        glBindVertexArray( 0 );
    
        glBindBuffer( GL_ELEMENT_ARRAY_BUFFER , 0 );
    }

I only get some sort of lighting if I rotate the mesh:如果我旋转网格,我只会得到某种照明:

图像

Normal ( No lighting):正常(无照明):

图像

I been trying to figure this out for a days but I am not sure what I did wrong.几天来我一直试图解决这个问题,但我不确定我做错了什么。 If you could help me that would be great.如果你能帮助我,那就太好了。

It turns out it was my order of indices having problem with triangle winding.事实证明,这是我的索引顺序有三角形绕组问题。 I fixed this by drawing the indices in counter clockwise order because of how my diffuse factor is calculated.由于我的漫射因子是如何计算的,我通过按逆时针顺序绘制索引来解决此问题。

unsigned int indices[]{
    0, 1, 2, // Front
    3, 1, 2, // Right
    3, 0, 2, // Left
    3, 1, 0  // Bottom
};

The transpose and inverse calculation is to correct non-uniform scale matrices.转置和逆计算是为了校正非均匀尺度矩阵。

this:这个:

Normal = mat3(transpose(inverse(transformation))) * normal;

looks suspicious the normal itself should be transformed into the same coordinate system as the light direction vector is in. As normal is a vector the w should be zero so I would expect either看起来很可疑,法线本身应该被转换到与光方向向量所在的坐标系相同的坐标系中。由于法线是一个向量,所以w应该为零,所以我希望要么

Normal = view * transformation * vec4( normal, 0.0f );

if the light direction is in camera coordinates or:如果光线方向在相机坐标中,或者:

Normal = transformation * vec4( normal, 0.0f );

if the light direction is in global world coordinates (which is more likely the case)...如果光线方向在全球世界坐标中(更可能是这种情况)......

Also setting shader output variable like gl_Position should be the last line of your shader or you risk GL implementation optimize out the rest of code after it on some implementations.此外,设置着色器 output 变量(如gl_Position应该是着色器的最后一行,否则您将面临 GL 实现在某些实现之后优化代码 rest 的风险。

btw.顺便提一句。 IIRC mat3(transpose(inverse(transformation))) is the same as mat3(transformation) in case the transformation but as Rabbid76 pointed out it has its purpose... IIRC mat3(transpose(inverse(transformation)))在转换的情况下与mat3(transformation) transformation ,但正如 Rabbid76 指出的那样,它有其目的......

One last thing I can think of is wrong normal direction (opposite or inconsistent) in such case I would try exchange:我能想到的最后一件事是错误的正常方向(相反或不一致),在这种情况下我会尝试交换:

max(dot(normalize(Normal), normalize(directionalLight.direction)), 0.0f);

with:和:

abs(dot(normalize(Normal), normalize(directionalLight.direction));

If it helps you have to check the normals or just negate the dot result...如果它有助于你必须检查法线或只是否定点结果......

For more info see:有关更多信息,请参阅:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM