形状取决于点光源顶点或片段着色器中的视角

时间:2014-03-18 16:34:54

标签: debugging opengl glsl lighting

在使用基本教程搞砸了很多东西之后,我将尝试通过顶点或片段着色器实现OpenGL光照。问题是,根据摄像机视角,背景中有一个形状,而结果不依赖于我是否在顶点或片段中进行:

enter image description here

取决于视角,它看起来有点像前面和右边的空中飞人,只有在几乎看不见的情况下才能显示出亮起的表面(不知何故让我想起了一个平截头体)。

现在我对点光源的理解是,与聚光灯不同,它可以照亮任何方向的所有物体,也不应该依赖于相机。

我现在主要关注本教程:http://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Diffuse_Reflectionhttp://en.wikibooks.org/wiki/GLSL_Programming/GLUT/Smooth_Specular_Highlights,而现在更像是第二个。

请不要怀疑我现在几乎把所有东西都传递给片段,只是为了试验它,如上所述,如果没有将任何东西传递给片段着色器,除了漫反射颜色并做所有事情之外,它会做同样的事情像第一篇教程中的顶点。另请注意,我还添加了一个纹理,这似乎可以很好地与coords。光位置目前处于世界空间,但也尝试在眼睛空间。我使用GLM在c ++中进行矩阵的大部分数学运算,只传递它。

FLOAT ViewMatrix[16]  =
{
    1.f, 0.f, 0.f, 0.f,
    0.f, -1.f, 0.f, 0.f,
    0.f, 0.f, -1.f, 0.f,
    0.f, 0.f, 0.f, 1.f
};
viewMat = glm::make_mat4(ViewMatrix);

// Identity
modelMat = glm::mat4(1.0f);

//gl_NormalMatrix ?
modelviewMat=modelMat*viewMat;
m_3x3_inv_transp = glm::inverseTranspose(glm::mat3(modelviewMat));

//viewMat inverted
viewMatinv = glm::inverse(viewMat);

projMat = glm::frustum(-RProjZ, +RProjZ, -Aspect*RProjZ, +Aspect*RProjZ, 1.0f, 32768.0);

我当前的顶点着色器看起来像这样(暂时忽略任何环境或镜面反射):

uniform sampler2D Texture0;
layout (location = 0) in vec3 v_coord;      // == gl_Vertex
layout (location = 1) in vec3 v_normal;


uniform mat3 m_3x3_inv_transp;              // == gl_NormalMatrix inverse transpose of modelviewMat
uniform mat4 projMat;
uniform mat4 viewMat;
uniform mat4 modelMat;
uniform mat4 modelviewMat;
uniform mat4 modelviewprojMat;              // == gl_ModelViewProjectionMatrix == projMat*viewMat*modelMat;
uniform mat4 viewMatinv;                    // == ViewMatrix inverse

out vec2 vTexCoords;
out vec3 vv_coord;
out vec3 vv_normal;
out vec3 vNormalDirection;

out mat3 vm_3x3_inv_transp;
out mat4 vprojMat;
out mat4 vviewMat;
out mat4 vmodelMat;
out mat4 vmodelviewMat;
out mat4 vmodelviewprojMat;
out mat4 vviewMatinv;

void main(void)
{
    //pass matrices also to fragment shader
    vprojMat            = projMat;
    vviewMat            = viewMat;
    vmodelMat           = modelMat;
    vmodelviewMat       = modelviewMat;
    vmodelviewprojMat   = modelviewprojMat;
    vm_3x3_inv_transp   = m_3x3_inv_transp;
    vviewMatinv         = viewMatinv;
    vv_coord            = v_coord;
    vv_normal           = v_normal;

    //Texture UV to fragment
    vTexCoords=TexCoords;

    //Texture UV Lightmap to fragment
    vLightTexCoords = LightTexCoords;

    vNormalDirection = m_3x3_inv_transp * v_normal;
    gl_Position = modelviewprojMat * vec4(v_coord, 1.0);
}

虽然片段着色器目前看起来像这样:

uniform sampler2D Texture0;

in vec2 vTexCoords;
in vec2 vLightTexCoords;
in vec3 vv_coord;
in vec3 vv_normal;
in vec3 vNormalDirection;

in mat3 vm_3x3_inv_transp;
in mat4 vprojMat;
in mat4 vviewMat;
in mat4 vmodelMat;
in mat4 vmodelviewMat;
in mat4 vmodelviewprojMat;
in mat4 vviewMatinv;

struct LightInfo                                                           
{  
    vec4 LightLocation;                                                                    
    vec3 DiffuseLightColor;
    vec3 AmbientLightColor;
    vec3 SpecularLightColor;
    vec3 spotDirection;
    float AmbientLightIntensity;
    float SpecularLightIntensity;
    float constantAttenuation;
    float linearAttenuation;
    float quadraticAttenuation;
    float spotCutoff;
    float spotExponent;
};
uniform LightInfo gLight; 


struct material
{
  vec4 diffuse;
};
material mymaterial = material(vec4(1.0, 0.8, 0.8, 1.0));       


out vec4 FragColor; 

void main (void)  
{  
    vec4 color = texture2D(Texture0, vTexCoords);     

    vec3 normalDirection = normalize(vNormalDirection);
    vec3 lightDirection;
    float attenuation;
    vec3 positionToLightSource;

    if (gLight.LightLocation.w == 0.0) // directional light?
    {
        attenuation = 1.0; // no attenuation
        lightDirection = normalize(vec3(gLight.LightLocation));
    } 
    else // point light or spotlight (or other kind of light) 
    {
        positionToLightSource = vec3(gLight.LightLocation - vec4(vv_coord,1.0));
    }
    vec3 diffuseReflection =  vec3(gLight.DiffuseLightColor) * max(0.0, dot(normalDirection, lightDirection));

    FragColor = color*vec4(diffuseReflection,1.0);             
}

我目前还省去了衰减以简化它,但是随着衰减,它也无法工作。将它设置为方向光,似乎很好,左边的墙完全被点亮,光的位置似乎也是正确的,因为在球体上是明显的。 然而,positionToLightSource似乎是罪魁祸首,但是由于LightLocation是修复的,它必须是vv_coord,我也尝试使用任何可用的矩阵进行任何可想象的转换版本,无论它是否有意义只是为了看它的行为,因为我在这里读了一些问题把矢量作为颜色可以帮助调试,但我无法弄清楚。如何看待一个vnormal的modelviewMat的逆转置?但无论如何它似乎并不关心视角...

我的猜测是,并非所有东西都在同一个空间(会很傻,但我会感到惊讶,因为它可以作为方向性光),或者由于某种原因f.e. normalDirection / vnormals是不对的 - 我不完全确定它,因为我从旧的游戏引擎中得到了这个应该可以工作的值,并且可以在某些教程和示例代码完美无缺地工作。

现在要做一个摘要,这不仅仅是关于当前的问题,因为它的来源可能超出了这些着色器的范围,因此可能没有解决方案,尽管我仍然希望即便如此有一个想法,但也如何正确调试这样的事情。我也尝试过glsldevil,但没有经验可能是对或错,在没有任何printf或其他东西的情况下进行调试时我仍然感到很无助。将矢量输出作为颜色也非常酷,但据说我不知道​​什么是“应该看起来正确” - 是否存在某种“有效调试输出”的存档?请仅针对OpenGL3或更新版本的建议:)

1 个答案:

答案 0 :(得分:1)

似乎是我获得法线信息的引擎需要先对屏幕坐标进行一些转换,所以绝对不是着色器的问题。将vv_coords和LightLocation相乘然后用modMat将它放在正确的空间中,一切看起来都像预期的那样。不过,如果有一些档案或文档可以从glsl内部进行某种“颜色调试”,那么我仍然感兴趣。 不管怎样,谢谢;)

稍后编辑,对于任何寻找调试提示的人:http://antongerdelan.net/opengl/debugshaders.html