使用OpenGL

时间:2016-01-30 04:52:28

标签: c++ opengl glsl framebuffer deferred-rendering

首先,我很抱歉这篇长篇文章试图让这一整天工作。

我对此有很多疑问,特别是因为我在C ++中使用继承来构建灯光。

我使用定向光作为光的核心模型,因为我可以给出光线方向并计算光线,然后在它上面我构建点光源,我只是计算从光到片段位置的矢量,最后对于聚光灯我使用点光源增加了截止角来创建聚光灯(只需忽略锥体外的任何东西)。我已经测试了灯光并且它们在前向渲染下工作正常但现在我想将我的灯光模型改为PBR(基本上只是改变我在定向光线中计算光线的方式)并移动到不同的渲染。

今天我开始研究延迟渲染,我可以得到位置,纹理,法线和深度缓冲区,但是在尝试渲染光时我遇到了问题。

这是第一个问题,第二个,因为每种类型的灯都有自己的着色器,我使用多态来构建它们。我的第二个问题是我可以循环使用C ++中的每个灯光并将每个灯光调用为渲染器,或者还有另一种方法可以在着色器中解决这个问题。 灯的原型是 编辑:我修复了一个小问题,即使用VP投影转换渲染四分之一但仍然无法绘制任何东西,我不知道FB现在是否正确工作。 Nvidia opengl调试器刚刚崩溃。

 Light(glm::vec3& color, float intensity, float ambient, ShaderProgram& lightShader);
 DirectionalLight(glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3& position = glm::vec3(0.0f, 0.0f, 0.0f), float intensity = 1.0f, float ambient = 0.0f, ShaderProgram& lightShader = ShaderProgram("Directional Light"));
    PointLight(glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3& position = glm::vec3(0.0f, 0.0f, 0.0f), float intensity = 1.0f, float ambient = 0.0f, LightAttenuation& lightAttenuation = LightAttenuation(), ShaderProgram& lightShader = ShaderProgram("Point Light"));
 SpotLight(glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f), glm::vec3& position = glm::vec3(0.0f, 0.0f, 0.0f),

我的渲染路径如下所示。

            glEnable(GL_DEPTH_TEST);
            glDepthFunc(GL_LESS);

        defferedShader_.startProgram();
        defferedShader_.setUniformMat4("VP", camera.getVP());


        glBindFramebuffer(GL_FRAMEBUFFER, deferredFbo);

        //the scene is small and does not need culling.
        for (auto* mesh : world.getMeshes()) {

            //mesh->draw(light->getLightShader());
            //mesh->draw(activeLight_->getLightShader());
            mesh->draw(defferedShader_);

            drawCallCounter += mesh->getMeshObjectSize();
        }

glBindFramebuffer(GL_FRAMEBUFFER, 0);
        defferedShader_.stopProgram();
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, positionFbo);
        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D, normalFbo);
        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D, albedoFbo);

               //This is where i got stuck, I would like to make directional light work then test other lights then test the whole program with more than one light
        //for (auto* light : world.getLights()) {
        //  //glEnable(GL_CULL_FACE);
        //  //glCullFace(GL_FRONT);
            glDisable(GL_DEPTH_TEST);
            activeLight_->getLightShader().startProgram();

            activeLight_->getLightShader().setUniformMat4("VP", camera.getVP());
            activeLight_->getLightShader().setUniformVec3("eyePosition", camera.getCameraPosition());

            //activeLight_->getLightShader();
            RenderQuad();

            activeLight_->getLightShader().stopProgram();

  //}

我开始构建的着色器代码是(PS我现在删除了阴影) 顶点着色器

    #version 410 core

#include "../Global/GlobalShader.inc"
#include "../Global/GlobalMesh.inc"

out vec3 Position;
out vec2 TexCoord;
//out vec4 ShadowCoord;

//uniform mat4 ShadowMatrix;

void main() {

    Position = position;
    TexCoord = texCoord;

    //ShadowCoord = ShadowMatrix * vec4(position, 1.0);
    gl_Position = VP * vec4(position, 1.0);
}

片段着色器 困扰我的一件事是我无法为gPosition,gPosition和gAlbedoSpec设置统一值,即使我使用它们,无论我在着色器中更改什么,输出都是相同的。

        #version 410 core

    #include "../Global/GlobalShader.inc"
    #include "../Global/GlobalMesh.inc"
    #include "../Global/GlobalLight.inc"
    //#include "../Global/ShadowSampling.inc"

    in vec3 Position;
    in vec2 TexCoord;
    //in vec4 ShadowCoord;

    uniform sampler2D gPosition;
    uniform sampler2D gNormal;
    uniform sampler2D gAlbedoSpec;

    float specularStrength = 32.0f; // to be impelemented

    out vec4 gl_FragColor;
    void main() {

        //vec4 lightning = vec4(0.0f);
        ////vec4 shadowMapping = vec4(0.0f);
        //
        vec3 FragPos = texture(gPosition, TexCoord).rgb;
        vec3 Normal = texture(gNormal, TexCoord).rgb;
        vec3 Diffuse = texture(gAlbedoSpec, TexCoord).rgb;
        float Specular = texture(gAlbedoSpec, TexCoord).a;

        //vec3 Diffuse = texture(gAlbedoSpec, TexCoord).rgb;
        //lightning = calculateDirectionalLight(directionalLight.light, directionalLight.position, Normal, Position, specularStrength, eyePosition, material, TexCoord);
        //gl_fragColor = vec3(Position, 1.0);
        //shadowMapping = calculateShadow(shadowMap, ShadowCoord, directionalLight.light.ambient);
        //gl_FragColor = vec4(Diffuse, 1.0);
        gl_FragColor = vec4(1.0); //vec4(Diffuse, 1.0);// lightning;//g * shadowMapping;

        //gl_FragColor = lightning;// * shadowMapping;
    }

in case you want to see global light 

    struct Light
{
    vec3 color;
    float intensity;
    float ambient;
};

struct DirectionalLight
{
    Light light;
    vec3 position;
};

struct Attenuation
{
    float constant;
    float linear;
    float quadratic;
};

struct PointLight
{
    Light light;
    Attenuation atten;
    vec3 position;
    float range;
};

struct SpotLight
{
    PointLight pointLight;
    //vec3 lookAt;
    vec3 direction;
    float cutOff;
};

vec3 GAMMA = vec3(1.0/2.2);

vec4 calculateDirectionalLight(Light light, vec3 direction, vec3 normal, vec3 worldPosition, float specularIntensity, vec3 eyePosition, Material material, vec2 texCoord)
{
        vec3 diffuseFactor = ( light.color * material.diffuse * vec3(texture(material.texture.diffuse, texCoord.st)) )
                                                 * (light.intensity * clamp(dot(normal, direction), 0.0, 1.0) ) ;

        vec3 viewDir = normalize(eyePosition - worldPosition);
        vec3 reflectDir = normalize(reflect(-direction, normal));

        float specularFactor = pow(clamp(dot(viewDir, reflectDir), 0.0, 1.0), specularIntensity);
        vec3 specularColor = ( light.color * material.specular * vec3(texture(material.texture.specular, texCoord.st)) ) * (specularFactor * material.shininess);

        return vec4(pow((diffuseFactor + specularColor + light.ambient + material.ambient), GAMMA), 1.0);
}

vec4 calculatePointLight(PointLight pointLight, vec3 normal, vec3 worldPosition, float specularIntensity, vec3 eyePosition, Material material, vec2 texCoord)
{
        // DO NOT NORMALIZE lightDirection, WE NEED IT TO CALCULATE THE DISTANCE TO COMPARE RANGE OF LIGHT
        vec3 lightDirection = pointLight.position - worldPosition;
        float distanceToPoint = length(lightDirection);

        // I dont like conditionals in shader, but since this is fragment based lighting i believe
        // this will speed-up things insetead of calculating the light
        if(distanceToPoint > pointLight.range)
                return vec4(0.0,0.0,0.0,0.0);

        vec4 light = calculateDirectionalLight(pointLight.light, lightDirection, normal, worldPosition,  specularIntensity, eyePosition, material, texCoord);

        // light attenuateion explained https://developer.valvesoftware.com/wiki/Constant-Linear-Quadratic_Falloff
        // http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Light+Attenuation+Shortcut
        float attenuation = max(pointLight.atten.constant
                                + pointLight.atten.linear * distanceToPoint
                                + pointLight.atten.quadratic * distanceToPoint * distanceToPoint,
                                1.0);

    return light / attenuation;
}

vec4 calculateSpotLight(SpotLight spotLight, vec3 normal, vec3 worldPosition, float specularIntensity, vec3 eyePosition, Material material, vec2 texCoord) 
{
    vec3 lightDirection = normalize(spotLight.pointLight.position - worldPosition);
    float spotFactor = dot(lightDirection, spotLight.direction);

    vec4 light = vec4(0.0f);
    if(spotFactor > spotLight.cutOff)
    {
        light = calculatePointLight(spotLight.pointLight, normal, worldPosition, specularIntensity, eyePosition, material, texCoord) * (1.0 - (1.0 - spotFactor)/(1.0 - spotLight.cutOff));
    }

    return light;
}

全局网格

   struct Texture {
    sampler2D diffuse;
    sampler2D specular;
    sampler2D normal;
    sampler2D ambient;
    sampler2D height;
    //vec2 texCoord;            
};

struct Material {
    vec3 ambient;           // Ka
    vec3 diffuse;           // Kd
    vec3 specular;          // Ks
    vec3 transmittance;     // Tr
    vec3 emission;          // Ke
    float shininess;        // Ns
    float ior;              // Ni
    float dissolve;         // Dissolve
    int illum;              // Illum
    Texture texture;
};

uniform Material material;

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 texCoord;
layout (location = 2) in vec3 normal;

全球着色器

    uniform mat4 VP;
uniform mat4 P;

绑定缓冲区并运行方向着色器后,我现在得到的是 enter image description here

并且仅作为示例看到场景这是位置缓冲区 enter image description here

1 个答案:

答案 0 :(得分:0)

修正了它。我把干净的缓冲区和颜色放在了错误的地方。应该是在我将缓冲区绑定到每帧的开头之后。

glEnable(GL_DEPTH_TEST);


glBindFramebuffer(GL_FRAMEBUFFER, deferredFbo);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    defferedShader_.startProgram();
    defferedShader_.setUniformMat4("VP", camera.getVP());
.
.
. rest of the code