D
D
Denis Koveshnikov2019-09-18 11:26:41
OpenGL
Denis Koveshnikov, 2019-09-18 11:26:41

Are interfaces officially brought to GLSL?

I decided to try to write something like ShaderBuilder, I started thinking about what and how,
I decided that I would use interface blocks to exchange data between shaders.
But as you know, in the vertex shader the block is declared as out , in the fragment shader as in . I decided to create a common file with macros, in which I would define interface depending on the type of shader, either as in or as out . At the stage of writing, I already see that the studio offers me a hint of this keyword in intelligence. I think it's great.
Then the thought came up, what if it works like in Cg from NVIDIA, by the way, I have a card of the same manufacturer. Decided to write this:

interface vs_out 
{
  vec3 get_color();  
};

When writing the vs_out declaration, I used data as members, because I still didn’t fully understand that the studio would tell you that interfaces cannot contain data, but only methods. Finally decided to try this
struct vs_out_impl : vs_out 
{
  vec3 get_color()
  {

    return vec3(1,0,0);
  }
}

Funny enough, interface is a reserved keyword in the official specification, and using it will result in a compilation error.
but if I write this, here is the full fragment shader code, for a quick search in which interesting place, find the comment "LOOK HERE!!!"
spoiler
#version 330 core
layout (location = 0) out vec4 FragColor;
layout (location = 1) out vec4 BrightColor;


interface vs_out 
{
  vec3 get_color();  
};


struct vs_out_impl : vs_out 
{
  vec3 get_color()
  {

    return vec3(1, 0,0);
  }
};

in VS_OUT {
    vec3 FragPos;
    vec3 Normal;
    vec2 TexCoords;
    vec4 FragPosLightSpace;
  vec3 oNormal;
} fs_in;

struct FogInfo {
  float maxDist;
  float minDist;
  vec3 color;
};
uniform FogInfo Fog;

uniform sampler2D diffuseMap;
uniform sampler2D specularMap;
uniform sampler2D emissiveMap;
uniform sampler2D shadowMap;

uniform float emissive_factor = 20.0f;
uniform bool has_emissive = false;
uniform bool has_specular = false;

uniform vec3 lightPos;
uniform vec3 viewPos;
uniform bool lightOn = true;
uniform bool bloomOn = true;
uniform float bloomThreshold = 0.0f;
uniform bool isTerrain = false;
uniform bool shadowOn = false;

float ShadowCalculation(vec4 fragPosLightSpace)
{
  if (!shadowOn)
    return 0.f;  
   // perform perspective divide
    vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
    // transform to [0,1] range
    projCoords = projCoords * 0.5 + 0.5;
  if (projCoords.z > 1.0)
    return 0.0;
    // get closest depth value from light's perspective (using [0,1] range fragPosLight as coords)
    float closestDepth = texture(shadowMap, projCoords.xy).r; 
    // get depth of current fragment from light's perspective
    float currentDepth = projCoords.z;
    // check whether current frag pos is in shadow
  float bias = 0.005;
  float shadow = 0.0f;//currentDepth - bias > closestDepth  ? 1.0 : 0.0;
  vec2 texelSize = 1.0f / textureSize(shadowMap,0);
  int factor = 4;
  for (int x = -1*factor; x <= 1*factor; x++)
  {
    for (int y = -1*factor; y <= 1*factor; y++)
    {
      float pcfDepth = texture(shadowMap, projCoords.xy + vec2(x,y)*texelSize).r;
      shadow += currentDepth - bias > pcfDepth ? 1.0 : 0.0;
    }
  }
  shadow /= 9.0 * factor * factor;
    return shadow; 
}

void main()
{
    //vec3 color = texture(diffuseMap, fs_in.TexCoords).rgb;
  vec3 color = vs_out_impl::get_color(); // СМОТРЕТЬ СЮДА!!!
  vec3 emissive = vec3(0.0f);
  if (has_emissive)
  {
    emissive = texture(emissiveMap, fs_in.TexCoords).rgb;
  }
    vec3 normal = normalize(fs_in.Normal);
    vec3 lightColor = vec3(1.0);
  if (!lightOn)
  {
    FragColor = vec4(color, 1.0f);
    return;
  }

    // ambient
    vec3 ambient = 0.15 * color; 
    // diffuse
    vec3 lightDir = normalize(lightPos - fs_in.FragPos);
    float diff = max(dot(lightDir, normal), 0.0);
    vec3 diffuse = diff * lightColor;
    // specular
    vec3 viewDir = normalize(viewPos - fs_in.FragPos);
    float spec = 0.0;

    vec3 halfwayDir = normalize(lightDir + viewDir);
    spec = pow(max(dot(normal, halfwayDir), 0.0), 64.0);
    vec3 specular = spec * lightColor;
  if (has_specular)
  {


    specular *= vec3(texture(specularMap, fs_in.TexCoords));
    //FragColor = vec4(10, 0, 0, 1.0);
    //specular *= vec3(10, 0, 0);

  }
  specular + vec3(10, 0, 0);
    // calculate shadow
    float shadow = ShadowCalculation(fs_in.FragPosLightSpace);

    vec3 lighting =(ambient + (1.0 - shadow) * (diffuse + specular)) * color + emissive * emissive_factor;

  vec3 result = lighting;
    // check whether result is higher than some threshold, if so, output as bloom threshold color
  #ifdef THRESHOLDED
    float brightness = dot(result, vec3(0.2126, 0.7152, 0.0722));
  if (brightness > bloomThreshold)

    //if(brightness > bloomThreshold)
        BrightColor = vec4(result, 1.0);
    else
        BrightColor = vec4(0.0, 0.0, 0.0, 1.0);
  #endif
    FragColor = vec4(result, 1.0);
}

then no compilation error occurs!
Moreover, you can see this result!
5d81e9769b393624129652.png
This is without using the method vs_out_impl::get_color():
5d81e982966cb715254398.png
Question: How is this possible? Where can I see a description of why this works?
Apparently NVIDIA is cunning and does not want to put up with the fact that Cg was not released , and now it unofficially supports the interesting goodies of this language.
PS
Although the usual inheritance of structures is not supported.

Answer the question

In order to leave comments, you need to log in

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question