gpt4 book ai didi

opengl - 通用 GLSL 光照着色器

转载 作者:行者123 更新时间:2023-12-03 00:16:44 25 4
gpt4 key购买 nike

基于像素的光照是许多 OpenGL 应用程序中的常见问题,因为标准 OpenGL 光照的质量非常差。

我想使用 GLSL 程序在我的 OpenGL 程序中实现基于每像素的照明,而不是每顶点的照明。只是漫反射照明,但至少有雾、纹理和纹理阿尔法。

我从 this shader 开始:

纹理.vert:

varying vec3 position;
varying vec3 normal;

void main(void)
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
gl_FrontColor = gl_Color;
gl_TexCoord[0] = gl_MultiTexCoord0;
normal = normalize(gl_NormalMatrix * gl_Normal);
position = vec3(gl_ModelViewMatrix * gl_Vertex);
}

纹理.frag:

uniform sampler2D Texture0;
uniform int ActiveLights;

varying vec3 position;
varying vec3 normal;

void main(void)
{
vec3 lightDir;
float attenFactor;
vec3 eyeDir = normalize(-position); // camera is at (0,0,0) in ModelView space
vec4 lightAmbientDiffuse = vec4(0.0,0.0,0.0,0.0);
vec4 lightSpecular = vec4(0.0,0.0,0.0,0.0);

// iterate all lights
for (int i=0; i<ActiveLights; ++i)
{
// attenuation and light direction
if (gl_LightSource[i].position.w != 0.0)
{
// positional light source
float dist = distance(gl_LightSource[i].position.xyz, position);
attenFactor = 1.0/( gl_LightSource[i].constantAttenuation +
gl_LightSource[i].linearAttenuation * dist +
gl_LightSource[i].quadraticAttenuation * dist * dist );
lightDir = normalize(gl_LightSource[i].position.xyz - position);
}
else
{
// directional light source
attenFactor = 1.0;
lightDir = gl_LightSource[i].position.xyz;
}
// ambient + diffuse
lightAmbientDiffuse += gl_FrontLightProduct[i].ambient*attenFactor;
lightAmbientDiffuse += gl_FrontLightProduct[i].diffuse * max(dot(normal, lightDir), 0.0) * attenFactor;
// specular
vec3 r = normalize(reflect(-lightDir, normal));
lightSpecular += gl_FrontLightProduct[i].specular *
pow(max(dot(r, eyeDir), 0.0), gl_FrontMaterial.shininess) *
attenFactor;
}
// compute final color
vec4 texColor = gl_Color * texture2D(Texture0, gl_TexCoord[0].xy);
gl_FragColor = texColor * (gl_FrontLightModelProduct.sceneColor + lightAmbientDiffuse) + lightSpecular;

float fog = (gl_Fog.end - gl_FogFragCoord) * gl_Fog.scale; // Intensität berechnen
fog = clamp(fog, 0.0, 1.0); // Beschneiden
gl_FragColor = mix(gl_Fog.color, gl_FragColor, fog); // Nebelfarbe einmischen
}

评论是德语,因为这是发布此代码的德国网站,抱歉。

但是这个着色器所做的只是让一切变得非常暗。根本没有光照效果 - 但着色器代码可以编译。如果我只在片段着色器中使用 GL_LIGHT0,那么它似乎可以工作,但仅适用于面向相机的多边形,而我的地板多边形非常暗。具有 RGBA 纹理的四边形也没有显示出透明度的迹象。我对模型 View 矩阵使用标准 glRotate/Translate,对多边形使用 glVertex/Normal。除了在非常大的表面上看起来很丑之外,OpenGL 照明工作得很好。我三次检查了我的法线,它们都很好。

上面的代码有问题吗?或者告诉我为什么没有通用的照明着色器来完成这个实际任务(基于点的光与距离衰减:如果你愿意的话,一根蜡烛) - 难道不应该只有一种正确的方法来做到这一点吗?我不想要凹凸/正常/视差/卡通/模糊/任何效果。我只是希望我的光照在更大的多边形上表现更好。

我发现的所有教程仅适用于当相机处于 0,0,0 方向与对象正交时照明单个对象。以上是唯一发现的至少看起来像我想做的事情。

最佳答案

我强烈建议您阅读 this article查看标准 ADS 闪电是如何在 GLSL 中完成的。这是 GL 4.0,但调整到您的版本没有问题:

此外,您还可以在 View (相机)空间中进行操作,因此不要否定眼睛矢量:

    vec3 eyeDir  = normalize(-position); 

我有与你非常相似的问题,因为我也否定了眼睛矢量,忘记了它被转换到 View 空间中。在当前场景中,你的漫反射和镜面反射计算似乎也是错误的。在你的地方,我不会使用完全来自固定管道的数据,否则在着色器中执行它有什么意义?以下是计算每片段 ADS 点闪电中的漫反射和镜面反射的方法:

void ads( int lightIndex,out vec3 ambAndDiff, out vec3 spec )
{


vec3 s = vec3(lights[lightIndex].Position - posOut) ;
vec3 v = normalize( posOut.xyz );
vec3 n = normalize(normOut);
vec3 h = normalize(v+s) ;// half vector (read in the web on what it is )


vec3 diffuse = ((Ka+ lights[lightIndex].Ld) * Kd * max( 0.0,dot(n, v) )) ;
spec = Ks * pow( max(0.0, dot(n,h) ), Shininess ) ;


ambAndDiff = diffuse ;

/// Ka-material ambient factor
/// Kd-material diffuse factor
/// Ks-material specular factor.
/// lights[lightIndex].Ld-lights diffuse factor;you may also add La and Ls if you want to have even more control of the light shading.
}

另外,我不建议您使用这里的衰减方程,它很难控制。如果您想添加基于光半径的衰减 there is this nice blog post:

关于opengl - 通用 GLSL 光照着色器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9780909/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com