分析VR中的着色器

时间:2017-08-08 09:37:05

标签: opengl directx shader augmented-reality

我想创建一个像世界坐标并创建波浪的着色器。我想分析视频并了解所需的步骤。 我不是在寻找代码,我只是在寻找有关如何使用GLSL或HLSL或任何其他语言实现代码的想法。

这里的低质量和fps GIF在案例链接中断了。

video

这是片段着色器:

#version 330 core

// Interpolated values from the vertex shaders
in vec2 UV;
in vec3 Position_worldspace;
in vec3 Normal_cameraspace;
in vec3 EyeDirection_cameraspace;
in vec3 LightDirection_cameraspace;

// highlight effect
in float pixel_z;       // fragment z coordinate in [LCS]
uniform float animz;    // highlight animation z coordinate [GCS]

// Ouput data
out vec4 color;
vec3 c;

// Values that stay constant for the whole mesh.
uniform sampler2D myTextureSampler;
uniform mat4 MV;
uniform vec3 LightPosition_worldspace;

void main(){

    // Light emission properties
    // You probably want to put them as uniforms
    vec3 LightColor = vec3(1,1,1);
    float LightPower = 50.0f;

    // Material properties
    vec3 MaterialDiffuseColor = texture( myTextureSampler, UV ).rgb;
    vec3 MaterialAmbientColor = vec3(0.1,0.1,0.1) * MaterialDiffuseColor;
    vec3 MaterialSpecularColor = vec3(0.3,0.3,0.3);

    // Distance to the light
    float distance = length( LightPosition_worldspace - Position_worldspace );

    // Normal of the computed fragment, in camera space
    vec3 n = normalize( Normal_cameraspace );
    // Direction of the light (from the fragment to the light)
    vec3 l = normalize( LightDirection_cameraspace );
    // Cosine of the angle between the normal and the light direction, 
    // clamped above 0
    //  - light is at the vertical of the triangle -> 1
    //  - light is perpendicular to the triangle -> 0
    //  - light is behind the triangle -> 0
    float cosTheta = clamp( dot( n,l ), 0,1 );

    // Eye vector (towards the camera)
    vec3 E = normalize(EyeDirection_cameraspace);
    // Direction in which the triangle reflects the light
    vec3 R = reflect(-l,n);
    // Cosine of the angle between the Eye vector and the Reflect vector,
    // clamped to 0
    //  - Looking into the reflection -> 1
    //  - Looking elsewhere -> < 1
    float cosAlpha = clamp( dot( E,R ), 0,1 );

    c = 
        // Ambient : simulates indirect lighting
        MaterialAmbientColor +
        // Diffuse : "color" of the object
        MaterialDiffuseColor * LightColor * LightPower * cosTheta / (distance*distance) +
        // Specular : reflective highlight, like a mirror
        MaterialSpecularColor * LightColor * LightPower * pow(cosAlpha,5) / (distance*distance);


    float z;
    z=abs(pixel_z-animz);   // distance to animated z coordinate
    z*=1.5;                 // scale to change highlight width
    if (z<1.0)
        {
        z*=0.5*3.1415926535897932384626433832795;   // z=<0,M_PI/2> 0 in the middle
        z=0.5*cos(z);
        color+=vec3(0.0,z,z);
        }

        color=vec4(c,1.0);

}

这是顶点着色器:

#version 330 core

// Input vertex data, different for all executions of this shader.
layout(location = 0) in vec3 vertexPosition_modelspace;
layout(location = 1) in vec2 vertexUV;
layout(location = 2) in vec3 vertexNormal_modelspace;

// Output data ; will be interpolated for each fragment.
out vec2 UV;
out vec3 Position_worldspace;
out vec3 Normal_cameraspace;
out vec3 EyeDirection_cameraspace;
out vec3 LightDirection_cameraspace;

out float pixel_z;      // fragment z coordinate in [LCS]

// Values that stay constant for the whole mesh.
uniform mat4 MVP;
uniform mat4 V;
uniform mat4 M;
uniform vec3 LightPosition_worldspace;

void main(){


    pixel_z=vertexPosition_modelspace.z;
    // Output position of the vertex, in clip space : MVP * position
    gl_Position =  MVP * vec4(vertexPosition_modelspace,1);

    // Position of the vertex, in worldspace : M * position
    Position_worldspace = (M * vec4(vertexPosition_modelspace,1)).xyz;

    // Vector that goes from the vertex to the camera, in camera space.
    // In camera space, the camera is at the origin (0,0,0).
    vec3 vertexPosition_cameraspace = ( V * M * vec4(vertexPosition_modelspace,1)).xyz;
    EyeDirection_cameraspace = vec3(0,0,0) - vertexPosition_cameraspace;

    // Vector that goes from the vertex to the light, in camera space. M is ommited because it's identity.
    vec3 LightPosition_cameraspace = ( V * vec4(LightPosition_worldspace,1)).xyz;
    LightDirection_cameraspace = LightPosition_cameraspace + EyeDirection_cameraspace;

    // Normal of the the vertex, in camera space
    Normal_cameraspace = ( V * M * vec4(vertexNormal_modelspace,0)).xyz; // Only correct if ModelMatrix does not scale the model ! Use its inverse transpose if not.

    // UV of the vertex. No special space for this one.
    UV = vertexUV;
}

1 个答案:

答案 0 :(得分:4)

我可以为此考虑两种方法:

  1. 基于3D重建

    所以你需要从动作中重建 3D 场景(这不是一件容易的事,也不是我喝茶的方式)。然后,您只需根据u,v纹理贴图坐标和动画时间将调制应用于选定的网格纹理。

    描述这样的主题不适合SO答案,所以你应该搜索关于这个主题的一些 CV 书籍/论文。

  2. 基于图像处理

    您只需根据颜色连续性/均匀性对图像进行分割。因此,您将具有相似颜色和强度的相邻像素(生长区域)组合在一起。完成后尝试根据类似于此的强度梯度伪造表面 3D 重建:

    之后创建u,v映射,其中一个轴是深度。

    完成后,只需将sin波效应调制应用于颜色。

    我将此分为两个阶段。第一遍将分段(我会选择 CPU 一侧),第二遍用于效果渲染(在 GPU 上)。

  3. 由于这是增强现实的形式,你还应该阅读:

    btw对该视频所做的事情既不是上述选项。他们很可能已经以矢量形式为该车提供了网格,并使用轮廓匹配来获得其在图像上的方向...并且照常渲染...因此它不适用于场景中的任何对象,但仅适用于该车。 ..这样的事情:

    [Edit1] GLSL高亮效果

    我举了这个例子:

    并将亮点添加到其中:

    1. 在CPU方面,我添加了animz变量

      它确定对象局部坐标系 LCS 中的z坐标,其中实际放置了高光。并且我在定时器中为渲染网格(立方体)的最小和最大z值设置动画+/-一些边距,因此高光不会立即从对象的一侧传送到另一侧......

      // global
      float animz=-1.0;
      // in timer
      animz+=0.05; if (animz>1.5) animz=-1.5; // my object z = <-1,+1> 0.5 is margin
      // render
      id=glGetUniformLocation(prog_id,"animz"); glUniform1f(id,animz);
      
    2. 顶点着色器

      我只是采用顶点z坐标并将其传递而不转换为片段

      out float pixel_z;      // fragment z coordinate in [LCS]
      pixel_z=pos.z;
      
    3. 片段着色器

      计算目标颜色c后(通过标准渲染)我计算pixel_zanimz的距离,如果小,那么我用sinwave调制c取决于距离。

      // highlight effect
      float z;
      z=abs(pixel_z-animz);   // distance to animated z coordinate
      z*=1.5;                 // scale to change highlight width
      if (z<1.0)
          {
          z*=0.5*3.1415926535897932384626433832795;   // z=<0,M_PI/2> 0 in the middle
          z=0.5*cos(z);
          c+=vec3(0.0,z,z);
          }
      
    4. 这里是完整的 GLSL 着色器......

      <强>顶点:

      #version 400 core
      #extension GL_ARB_explicit_uniform_location : enable
      layout(location = 0) in vec3 pos;
      layout(location = 2) in vec3 nor;
      layout(location = 3) in vec3 col;
      layout(location = 0) uniform mat4 m_model;  // model matrix
      layout(location =16) uniform mat4 m_normal; // model matrix with origin=(0,0,0)
      layout(location =32) uniform mat4 m_view;   // inverse of camera matrix
      layout(location =48) uniform mat4 m_proj;   // projection matrix
      out vec3 pixel_pos;     // fragment position [GCS]
      out vec3 pixel_col;     // fragment surface color
      out vec3 pixel_nor;     // fragment surface normal [GCS]
      
      // highlight effect
      out float pixel_z;      // fragment z coordinate in [LCS]
      
      void main()
          {
          pixel_z=pos.z;
          pixel_col=col;
          pixel_pos=(m_model*vec4(pos,1)).xyz;
          pixel_nor=(m_normal*vec4(nor,1)).xyz;
          gl_Position=m_proj*m_view*m_model*vec4(pos,1);
          }
      

      <强>片段:

      #version 400 core
      #extension GL_ARB_explicit_uniform_location : enable
      layout(location =64) uniform vec3 lt_pnt_pos;// point light source position [GCS]
      layout(location =67) uniform vec3 lt_pnt_col;// point light source color&strength
      layout(location =70) uniform vec3 lt_amb_col;// ambient light source color&strength
      in vec3 pixel_pos;      // fragment position [GCS]
      in vec3 pixel_col;      // fragment surface color
      in vec3 pixel_nor;      // fragment surface normal [GCS]
      out vec4 col;
      
      // highlight effect
      in float pixel_z;       // fragment z coordinate in [LCS]
      uniform float animz;    // highlight animation z coordinate [GCS]
      
      void main()
          {
          // standard rendering
          float li;
          vec3 c,lt_dir;
          lt_dir=normalize(lt_pnt_pos-pixel_pos); // vector from fragment to point light source in [GCS]
          li=dot(pixel_nor,lt_dir);
          if (li<0.0) li=0.0;
          c=pixel_col*(lt_amb_col+(lt_pnt_col*li));
          // highlight effect
          float z;
          z=abs(pixel_z-animz);   // distance to animated z coordinate
          z*=1.5;                 // scale to change highlight width
          if (z<1.0)
              {
              z*=0.5*3.1415926535897932384626433832795;   // z=<0,M_PI/2> 0 in the middle
              z=0.5*cos(z);
              c+=vec3(0.0,z,z);
              }
          col=vec4(c,1.0);
          }
      

      预览:

      preview

      此方法不需要纹理也不需要u,v映射。

      [Edit2]以起点突出显示

      有很多方法可以实现它。我选择距离起点的距离作为突出显示参数。因此,重点将从各个方向的角度增长。此处预览两个不同的触摸点位置:

      preview preview

      白色粗体十字是为视觉检查而呈现的触摸点的位置。代码如下:

      <强>顶点:

      // Vertex
      #version 400 core
      #extension GL_ARB_explicit_uniform_location : enable
      layout(location = 0) in vec3 pos;
      layout(location = 2) in vec3 nor;
      layout(location = 3) in vec3 col;
      layout(location = 0) uniform mat4 m_model;  // model matrix
      layout(location =16) uniform mat4 m_normal; // model matrix with origin=(0,0,0)
      layout(location =32) uniform mat4 m_view;   // inverse of camera matrix
      layout(location =48) uniform mat4 m_proj;   // projection matrix
      out vec3 LCS_pos;       // fragment position [LCS]
      out vec3 pixel_pos;     // fragment position [GCS]
      out vec3 pixel_col;     // fragment surface color
      out vec3 pixel_nor;     // fragment surface normal [GCS]
      
      void main()
          {
          LCS_pos=pos;
          pixel_col=col;
          pixel_pos=(m_model*vec4(pos,1)).xyz;
          pixel_nor=(m_normal*vec4(nor,1)).xyz;
          gl_Position=m_proj*m_view*m_model*vec4(pos,1);
          }
      

      <强>片段:

      // Fragment
      #version 400 core
      #extension GL_ARB_explicit_uniform_location : enable
      layout(location =64) uniform vec3 lt_pnt_pos;// point light source position [GCS]
      layout(location =67) uniform vec3 lt_pnt_col;// point light source color&strength
      layout(location =70) uniform vec3 lt_amb_col;// ambient light source color&strength
      in vec3 LCS_pos;        // fragment position [LCS]
      in vec3 pixel_pos;      // fragment position [GCS]
      in vec3 pixel_col;      // fragment surface color
      in vec3 pixel_nor;      // fragment surface normal [GCS]
      out vec4 col;
      
      // highlight effect
      uniform vec3  touch;    // highlight start point [GCS]
      uniform float animt;    // animation parameter <0,1> or -1 for off
      uniform float size;     // highlight size
      
      void main()
          {
          // standard rendering
          float li;
          vec3 c,lt_dir;
          lt_dir=normalize(lt_pnt_pos-pixel_pos); // vector from fragment to point light source in [GCS]
          li=dot(pixel_nor,lt_dir);
          if (li<0.0) li=0.0;
          c=pixel_col*(lt_amb_col+(lt_pnt_col*li));
          // highlight effect
          float t=length(LCS_pos-touch)/size; // distance from start point
          if (t<=animt)
              {
              t*=0.5*3.1415926535897932384626433832795;   // z=<0,M_PI/2> 0 in the middle
              t=0.75*cos(t);
              c+=vec3(0.0,t,t);
              }
          col=vec4(c,1.0);
          }
      

      您可以使用制服来控制它:

      uniform vec3  touch;    // highlight start point [GCS]
      uniform float animt;    // animation parameter <0,1> or -1 for off
      uniform float size;     // max distance of any point of object from touch point