使用 OpenGL 使用延迟渲染绑定 FBO 后卡在渲染灯上
Posted
技术标签:
【中文标题】使用 OpenGL 使用延迟渲染绑定 FBO 后卡在渲染灯上【英文标题】:Stuck on rendering lights after binding FBO using deffered rendering using OpenGL 【发布时间】:2016-01-30 04:52:28 【问题描述】:首先我很抱歉在尝试了一整天的工作后写了这么长的帖子。
我对此有很多疑问,尤其是因为我在 C++ 中使用继承来构建灯光。
我使用定向光作为光的核心模型,因为我可以给出光的方向,它会计算光,然后在它之上我构建点光,我只计算从光到片段位置的矢量,最后对于聚光灯,我使用带有截止角的点光来创建聚光灯(只需忽略圆锥外的任何东西)。我已经测试了灯光,它们在前向渲染中工作得很好,但现在我想将我的灯光模型更改为 PBR(基本上只是改变我在定向光中计算灯光的方式)并转向不同的渲染。
今天我开始研究延迟渲染,我可以获得位置、纹理、法线和深度缓冲区,但是在尝试渲染灯光时遇到了问题。
这是第一个问题,第二个问题,因为每种类型的光都有自己的着色器,我使用多态性构建它们。我的第二个问题是我可以循环遍历 C++ 中的每个灯光并将每个灯光称为渲染器,或者还有另一种方法可以在着色器中解决这个问题。 灯的原型是 编辑:我修复了一个小问题,即 iw 用 VP 投影转换渲染 quat,但我仍然无法绘制任何东西,我不知道 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;
绑定缓冲区并运行定向着色器后,我现在得到的是
作为查看场景的示例,这是位置缓冲区
【问题讨论】:
ID:opengl.org/wiki/Shader_Subroutine 【参考方案1】:修复它。我把干净的缓冲区和颜色放在了错误的地方。它应该在我绑定缓冲区之后而不是在每一帧的开头。
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
【讨论】:
以上是关于使用 OpenGL 使用延迟渲染绑定 FBO 后卡在渲染灯上的主要内容,如果未能解决你的问题,请参考以下文章