openGL的工作原理说明

时间:2015-08-13 15:21:53

标签: opengl opengl-es glsl shader ambient

我试图了解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 =( - revationLight)*(gl_NormalMatrix);

  • 为什么他们使用* 2.0) - 1.0来计算normalvector?用 Normal = normalize(gl_NormalMatrix * gl_Normal);

    是不可能的

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

2 个答案:

答案 0 :(得分:2)

懒得完全分析代码而没有你要发送到着色器的提示器上下文...但你的子问题很容易:

  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或您的轴视图方向为负[{1}}(取决于矩阵的格式)。没有背景信息很难确定。

  3. 为什么我们使用负旋转光? Z

    最有可能与bullet 2相同的原因

  4. 为什么他们使用LightDirection = (-rotationLight ) * (gl_NormalMatrix);来计算normalvector?

    着色器使用normal/bump mapping,这意味着您获得的纹理具有编码为RGB的法线向量。由于RGB纹理被限制在*2.0)-1.0范围内,法线向量坐标在<0,1>范围内,因此您只需要重新缩放纹素即可:

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

    这将获得多边形坐标系中的法线向量,因此您需要将其转换为方程式的坐标系。通常是全球世界空间或相机空间。如果您的法线/凹凸贴图已经标准化,则无需标准化。普通纹理与颜色不同......

    • 平面有<-1,+1>所以RGB格式为normal=(0.0,0.0,+1.0)

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

    但是,您可以使用(0.5,0.5,1.0)

    但是这将消除凹凸/法线贴图,而你只需要平面。像这样:

  5. <强>灯

    Normal = normalize( gl_NormalMatrix * gl_Normal);看起来像光线方向。这个围绕vec3(fCosTime0_X,0, fSinTime0_X)轴旋转。如果您想将光线方向更改为其他内容,只需将其设为制服并将其直接传递到着色器而不是y

答案 1 :(得分:0)

  

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

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

  

如果我想让光从上面来到茶壶的底部怎么办?

如果您希望光线在不同方向旋转,只需将sin和cos值传递到此处的不同空间坐标:vec3 rotationLight = vec3(fCosTime0_X,fSinTime0_X, 0);