[英]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:有关更多信息,请参阅:
w=1
as the matrix used has no offset so it does not matter w=1
,因为使用的矩阵没有偏移所以没关系
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.