【问题标题】:Explanation of working principle of openGL [closed]openGL工作原理说明[关闭]
【发布时间】:2015-08-13 15:21:53
【问题描述】:

我试图了解 openGL 中的编码是如何工作的。我在互联网上找到了这段代码,我想清楚地理解它。

对于我的顶点着色器,我有:

顶点

uniform vec3 fvLightPosition;
    varying vec2 Texcoord;
    varying vec2 Texcoordcut;
    varying vec3 ViewDirection;
    varying vec3 LightDirection;
    uniform mat4 extra;

    attribute vec3 rm_Binormal;
    attribute vec3 rm_Tangent;

    uniform float fSinTime0_X;
    uniform float fCosTime0_X;

    void main( void )
    {
       gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex * extra;
       Texcoord    = gl_MultiTexCoord0.xy;
       Texcoordcut   = gl_MultiTexCoord0.xy;

       vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;

       vec3 rotationLight = vec3(fCosTime0_X,0, fSinTime0_X);
       ViewDirection  =  - fvObjectPosition.xyz;
       LightDirection = (-rotationLight ) * (gl_NormalMatrix); 
    }

对于我的片段着色器,我在图片上创建了一个白色以在其中创建一个洞。 :

uniform vec4 fvAmbient;
uniform vec4 fvSpecular;
uniform vec4 fvDiffuse;
uniform float fSpecularPower;

uniform sampler2D baseMap;
uniform sampler2D bumpMap;

varying vec2 Texcoord;
varying vec2 Texcoordcut;
varying vec3 ViewDirection;
varying vec3 LightDirection;

void main( void )
{
   vec3  fvLightDirection = normalize( LightDirection );
   vec3  fvNormal         = normalize( ( texture2D( bumpMap, Texcoord ).xyz * 2.0 ) - 1.0 );
   float fNDotL           = dot( fvNormal, fvLightDirection ); 
   vec3  fvReflection     = normalize( ( ( 2.0 * fvNormal ) * fNDotL ) - fvLightDirection ); 
   vec3  fvViewDirection  = normalize( ViewDirection );
   float fRDotV           = max( 0.0, dot( fvReflection, fvViewDirection ) );
   vec4  fvBaseColor      = texture2D( baseMap, Texcoord );

   vec4  fvTotalAmbient   = fvAmbient * fvBaseColor; 
   vec4  fvTotalDiffuse   = fvDiffuse * fNDotL * fvBaseColor; 
   vec4  fvTotalSpecular  = fvSpecular * ( pow( fRDotV, fSpecularPower ) );


   if(fvBaseColor == vec4(1,1,1,1)){ 
      discard;
   }else{ 
     gl_FragColor = ( fvTotalDiffuse + fvTotalSpecular );
   }



}

谁能向我解释一下一切都是做什么的?我理解它的基本思想。但不是经常为什么需要它,当你使用其他变量时会发生什么?发生的事情是茶壶周围的光在时间里来来去去。这如何与 cosinus 和 sinus 变量正确关联?如果我想让光线从上方射到茶壶底部怎么办?

还有,

  • 这几行是什么意思?

    vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;

  • 为什么这里的变量前面有一个减号?

    ViewDirection = - fvObjectPosition.xyz;

  • 我们为什么要使用负旋转光照?

    LightDirection = (-rotationLight) * (gl_NormalMatrix);

  • 为什么他们使用 *2.0 ) - 1.0 来计算法线向量? Normal = normalize(gl_NormalMatrix * gl_Normal); 不是不可能吗?

    vec3 fvNormal = normalize((texture2D(bumpMap, Texcoord).xyz * 2.0) - 1.0);

【问题讨论】:

  • 也许这只是我,但我认为你的问题太宽泛了。您告诉我们您了解基本概念,但是您的进一步问题并不是很具体。代码是照明模型的实现,我猜是 Phong,您可以在此处查看模型的工作原理:en.wikipedia.org/wiki/Phong_reflection_model 您需要对矩阵和矢量数学有基本的了解才能继续学习。了解模型后,请观察代码仅更改光的入射角度。也许您可以重新表述您的问题,或者从基础开始。
  • 我更新了一些我不明白的细节。
  • @TimDirks 添加了答案,编辑了您的标签(添加 [glsl] 以启用语法突出显示)

标签: opengl opengl-es glsl shader ambient


【解决方案1】:

如果没有您发送给着色器的适当上下文,就懒得全面分析代码......但是您的子问题很简单:

  1. 这几行是什么意思? vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;

    这会将gl_Vertex(多边形边缘点)从对象/模型坐标系转换为相机坐标系。换句话说,它应用了顶点的所有旋转和平移。 z 轴是指向或指向屏幕的摄像机视图轴,x,y 轴与屏幕相同。尚未应用任何投影/剪报/夹具!结果点存储在fvObjectPosition 4D 矢量(x,y,z,w) 我强烈建议您阅读Understanding 4x4 homogenous transform matrices 并且那里的子链接也值得研究。

  2. 为什么这里的变量前面有一个减号? ViewDirection = - fvObjectPosition.xyz;

    很可能是因为您需要从表面到相机的方向,所以 direction_from_surface=camera_pos-surface_pos 因为您的 surface_pos 已经在相机坐标系中,那么相同坐标中的相机位置是 (0,0,0) 所以结果是 direction_from_surface=(0,0,0)-surface_pos=-surface_pos 或者你得到了负Z 轴视图方向(取决于矩阵的格式)。没有背景信息很难确定。

  3. 我们为什么要使用负旋转光照? LightDirection = (-rotationLight ) * (gl_NormalMatrix);

    很可能出于与第 2 条相同的原因

  4. 他们为什么使用*2.0)-1.0 来计算法线向量?

    着色器使用normal/bump mapping,这意味着你得到了一个法线向量编码为RGB的纹理。由于 RGB 纹理被限制在<0,1> 范围内,而法线向量坐标在<-1,+1> 范围内,那么您只需要重新调整纹理像素所以:

    • RGB*2.0<0,2> 范围内
    • RGB*2.0-1.0<-1,+1> 范围内

    这会在多边形坐标系中获得您的法线向量,因此您需要将其转换为您的方程使用的坐标系。通常是全局世界空间或相机空间。如果您的法线/凹凸贴图已经规范化,则不需要规范化。正常的纹理具有独特的颜色...

    • 平面有normal=(0.0,0.0,+1.0),所以在RGB中它将是(0.5,0.5,1.0)

    这是纹理中常见的蓝色/洋红色(参见上面的链接)。

    但是你可以使用Normal = normalize( gl_NormalMatrix * gl_Normal);

    但这会消除凹凸贴图/法线贴图,而您只会得到平坦的表面。像这样的:

  5. vec3(fCosTime0_X,0, fSinTime0_X) 看起来像光的方向。这个围绕y 轴旋转。如果您想将光线方向更改为其他方向,只需将其设置为统一并将其直接传递给着色器而不是 fCosTime0_X,fSinTime0_X

【讨论】:

    【解决方案2】:

    这如何与 cosinus 和 sinus 变量正确关联?

    您可以通过 glUniform 函数将数据发送到着色器统一变量。例如:在您的顶点着色器中,您有 2 个浮点值,因此您将每次使用不同的位置和不同的值调用 glUniform1f 两次。
    或者您可以将浮点变量粘贴到一个 vec2 变量,如下所示:
    uniform vec2 fSinValues; 并用glUniform2f(location, sinVal, cosVal); 填充它们

    如果我想让光线从上方射到茶壶底部怎么办?

    如果你想让你的光在不同的方向旋转,只需将 sin 和 cos 值传递给不同的空间坐标:vec3 rotationLight = vec3(fCosTime0_X,fSinTime0_X, 0);

    【讨论】:

    • 这一行是什么意思? * vec4 fvObjectPosition = gl_ModelViewMatrix * gl_Vertex;为什么在变量之前有一个减号? ViewDirection = - fvObjectPosition.xyz;
    • 假设你在空间中有一个立方体。您想绘制立方体,因此它看起来像是在空间中的某个地方。为了达到这个效果,你必须将立方体的每个顶点乘以一组矩阵。因此,通过将顶点乘以矩阵,它将立方体从 3D 空间转换为 2D 空间,也就是您的屏幕。如果我没记错的话,ViewDirection = - fvObjectPosition.xyz 这段代码会计算你的视线相对于顶点的方向,这样你就可以计算出适当的光照。
    猜你喜欢
    • 1970-01-01
    • 2019-06-07
    • 1970-01-01
    • 2011-08-08
    • 2013-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多