glLightfv GL_POSITION GL_LINEAR_ATTENUATION glsl OpenGL3 或 OpenGL4(位置光)

Posted

技术标签:

【中文标题】glLightfv GL_POSITION GL_LINEAR_ATTENUATION glsl OpenGL3 或 OpenGL4(位置光)【英文标题】:glLightfv GL_POSITION GL_LINEAR_ATTENUATION glsl OpenGL3 or OpenGL4 (positional light) 【发布时间】:2014-03-11 10:37:43 【问题描述】:

好的,我再次迷失在大量的教程中,这些教程似乎将旧 GL 版本与 GL3 和 4 混为一谈。大多数教程都使用不推荐使用的代码,我正在寻找合适的 OpenGL3,或者甚至更好的 OpenGL4 替代品对于这个伪代码:

GLfloat LightRadius=0.5f; //or whatever value.
glLightf(NumLights, GL_LINEAR_ATTENUATION, LightRadius);
GLfloat light_position[] =  LightLoc.X,LightLoc.Y, LightLoc.Z, 1 ; //World space location
glLightfv(NumLights, GL_POSITION, light_position);

用于 phong 照明

vs 可能如下所示:

#version 330
layout (location = 0) in vec3 Position;
layout (location = 1) in vec3 PositionNormals;

uniform mat4 projMat;
uniform mat4 viewMat;
uniform mat4 modelMat;

out vec3 vposition;
out vec3 vnormal;

out mat4 vprojMat;
out mat4 vviewMat;
out mat4 vmodelMat;

void main(void)


    vprojMat    = projMat; // from what I understood I need those in the fs as well..?
    vviewMat    = viewMat;
    vmodelMat   = modelMat;

    vposition   = vec3(viewMat * modelMat * vec4 (Position, 1.0));
    vnormal     = vec3(viewMat * modelMat * vec4 (PositionNormals, 0.0));

    gl_Position     = projMat * vec4(vposition_eye, 1.0);


和fs:

in vec3 vposition;
in vec3 vnormal;

in mat4 vprojMat;
in mat4 vviewMat;
in mat4 vmodelMat;

struct LightInfo                                                           
  
    vec3 LightLocation;                                                                   
    vec3 DiffuseLightColor;
    vec3 AmbientLightColor;
    vec3 SpecularLightColor;
    float AmbientLightIntensity;
    float SpecularLightIntensity;
    float LightRadius;
;
uniform LightInfo gLight;                                         

out vec4 FragColor; 

void main (void)  
  
    //Diffuse Lighting

    // and here I am lost. Was trying to do in eyespace, but the light seems to float more somewhere instead of having a fixed position.

    vec3 light_position = ??? gLight.LightLocation; // probably normalized?

    float dot_prod = ??? 
    dot_prod = max (dot_prod, 0.0);
    vec3 diffuse_intensity = gLight.DiffuseLightColor * dot_prod; // final diffuse intensity


    FragColor=diffuse_intensity;

这个想法相当简单,只是房间内的一盏灯向各个方向(如太阳)照射,并具有取决于任意半径的给定衰减。我似乎无法找出它背后的数学原理。如果这是一个愚蠢的问题,请原谅我,但我读得越多,我就越困惑。我知道我需要计算漫射光的点、表面的朝向(法线)和从表面到光源的方向,但我不能把它们放在一起。

【问题讨论】:

改变了 GLfloat light_position[] = LightLoc.X,LightLoc.Y, LightLoc.Z, 0 ;到 GLfloat light_position[] = LightLoc.X,LightLoc.Y, LightLoc.Z, 1 ;在我的伪代码中,首先应该是 1,抱歉 :) - 除此之外仍在尝试通过它。不管怎样,谢谢你的第一个答案 经过大量阅读,如果我再次混淆,请原谅我,我越来越得出结论,我的问题在适当的替换可能就在这里(我以后需要位置光):normal = normalize(gl_NormalMatrix * gl_Normal); - 这在所有“旧”教程中都使用过。现在我想知道,gl_NormalMatrix 应该来自我读到的 ModelView 矩阵的逆转置?但是对于 gl_Normal 我发现了多种解释,这些解释有很大不同... 【参考方案1】:

您应该在同一坐标系中拥有所有顶点和灯光数据。如果你在世界坐标中发送光的位置,你也应该用世界空间中的法线制作点积。在性能方面,最好在眼睛/相机空间发送光线。为此,您应该像这样调用 glLightfv:

// The 4th component of the light position should be 1, because it's a position, not a direction
GLfloat light_position[] =  LightLoc.X,LightLoc.Y, LightLoc.Z, 1 ; //World space location
// TODO: Change to eye space multiplying by the inverse of the modelView matrix
Matrix4 invModelView;
inverseOrtho(viewMatrix * modelMatrix, invModelView);
transformVector4(light_position, invModelView);
glLightfv(NumLights, GL_POSITION, light_position);    // Send light in eye space

如果你有眼睛空间中的灯光,那么像素着色器比计算世界空间中的所有灯光更简单。

void main (void)  
  
    //Diffuse Lighting

    vec3 light_position = gLight.LightLocation;    // Light position in eye space

    // calculate the light direction from the light to the vertex being iluminated
    float dot_prod = dot((vposition - light_position).normalize(), vnormal);
    dot_prod = max (dot_prod, 0.0);
    vec3 diffuse_intensity = gLight.DiffuseLightColor * dot_prod; // final diffuse intensity

    FragColor=diffuse_intensity;

【讨论】:

我很确定惯例是在眼睛/相机空间中进行照明,除非在切线空间中涉及法线贴图。这样您就可以避免为每个对象变换灯光位置,并且镜面反射分量计算更简单。我唯一能想到的就是仅在对象空间中进行漫反射,不需要正常的矩阵乘法。 是的,光线应该通过眼睛/相机空间:),我要编辑我的答案 或者你可以不做这些并且像所有主要的延迟着色图形引擎(例如Unreal,CryENGINE)一样在世界空间中做所有事情。我个人在世界空间中自己做所有事情,因为它使我大量使用的几个后处理过滤器更有效。 确实我更喜欢呆在世界空间里,这一切的翻译似乎在我的脑海里打了个结。当我完成我的工作后,我会尝试更多,但是任何人都可以为我提供一个使用除 glLightf 之外的制服的例子吗?由于我目前主要是为了学习而这样做,因此我尝试将所有数学知识都放在它背后,而不是依赖固定函数。据说 glLightf 已经在内部做了一些翻译,也许这导致我仍然存在理解上的差距,我显然不明白那里真正做了什么。

以上是关于glLightfv GL_POSITION GL_LINEAR_ATTENUATION glsl OpenGL3 或 OpenGL4(位置光)的主要内容,如果未能解决你的问题,请参考以下文章

opengl 运行白屏

OpenGL大作业

未声明的标识符“gl_Position”

WebGL—gl_Position gl_FragCoord gl_PointCoord 区别

WebGL—gl_Position gl_FragCoord gl_PointCoord 区别

替换 gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;