3

ようやく GBuffer が機能するようになりましたが (実際にはそうではありません)、奇妙な問題がいくつかあり、その理由がわかりません。

画面に法線テクスチャを描画すると、常に法線が表示されます (青い色が常にカメラを指しています)。正しく説明する方法がわからないので、いくつかの画面を次に示します。

(これが私の照明パスがかなり奇妙に見える問題だと思います)

GBuffer を作成する方法は次のとおりです。

glGenFramebuffers(1, &fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);

// generate texture object
glGenTextures(GBUFFER_NUM_TEXTURES, textures);
for (unsigned int i = 0; i < 4; i++)
{
    glBindTexture(GL_TEXTURE_2D, textures[i]);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, width, height, 0, GL_RGBA, GL_FLOAT, 0);
    glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, textures[i], 0);

    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}

// generate depth texture object
glGenTextures(1, &depthStencilTexture);
glBindTexture(GL_TEXTURE_2D, depthStencilTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32, width, height, 0, GL_DEPTH_COMPONENT, GL_FLOAT,NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, depthStencilTexture, 0);

// generate output texture object
glGenTextures(1, &outputTexture);
glBindTexture(GL_TEXTURE_2D, outputTexture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB32F, width, height, 0, GL_RGB, GL_FLOAT, NULL);
glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT4, GL_TEXTURE_2D, outputTexture, 0);

GLenum Status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
assert(Status == GL_FRAMEBUFFER_COMPLETE);

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);

ここでジオメトリパス:

glEnable(GL_DEPTH_TEST);
glDepthMask(true);
glCullFace(GL_BACK);

glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);

GLenum DrawBuffers[] = {GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1, GL_COLOR_ATTACHMENT2, GL_COLOR_ATTACHMENT3};
glDrawBuffers(GBUFFER_NUM_TEXTURES, DrawBuffers);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glLoadIdentity();
camera.Render();

geoProgram->Use();

GLfloat mat[16];

glPushMatrix();
glTranslatef(0,0,-20);
glRotatef(rot, 1.0, 0, 0);
glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, mat);
glutSolidCube(5);
glPopMatrix();

glPushMatrix();
glTranslatef(0,0,0);
glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, mat);
gluSphere(sphere, 3.0, 20, 20);
glPopMatrix();

glDepthMask(false);
glDisable(GL_DEPTH_TEST);

ジオメトリ パス シェーダーは次のとおりです。

[Vertex]
varying vec3 normal;
varying vec4 position;
uniform mat4 worldMatrix;

void main( void )
{       
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    position = worldMatrix * gl_Vertex;
    normal = (worldMatrix * vec4(gl_Normal, 0.0)).xyz;
    gl_TexCoord[0]=gl_MultiTexCoord0;
}


[Fragment]
varying vec3 normal;
varying vec4 position;

void main( void )
{
    gl_FragData[0] = vec4(0.5, 0.5, 0.5, 1);//gl_Color;
    gl_FragData[1] = position;
    gl_FragData[2] = vec4(normalize(normal),0);
    gl_FragData[3] = vec4(gl_TexCoord[0].st, 0, 0);
}

長い質問/コード フラグメントで申し訳ありませんが、次に何をすべきかわかりません。他の GBuffer 実装ですべてをチェックしましたが、エラーを見つけることができませんでした。

//編集:

問題は gbuffer ではなく、ライティング パスです。私はそれをたくさんいじりましたが、うまくいきません:(

ライティングパスは次のとおりです。

[vs]
void main( void )
{
   gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}

[fs]
uniform sampler2D colorMap;
uniform sampler2D positionMap;
uniform sampler2D normalMap;
uniform sampler2D texcoordMap;

uniform vec2 screenSize;
uniform vec3 pointLightPostion;
uniform vec3 pointLightColor;
uniform float pointLightRadius;


void main( void )
{
    float lightDiffuse = 0.5;
    float lightSpecular = 0.7;
    vec3 lightAttenuation = vec3(1.4, 0.045, 0.00075);

    vec2 TexCoord = gl_FragCoord.xy / screenSize.xy;
    vec3 WorldPos = texture2D(positionMap, TexCoord).xyz;
    vec3 Color = texture(colorMap, TexCoord).xyz;
    vec3 normal = texture(normalMap, TexCoord).xyz;
    normal = normalize(normal);

    vec3 lightVector = WorldPos - pointLightPostion;
    float dist = length(lightVector);
    lightVector = normalize(lightVector);

    float nDotL = max(dot(normal, lightVector), 0.0);
    vec3 halfVector = normalize(lightVector - WorldPos);
    float nDotHV = max(dot(normal, halfVector), 0.0);

    vec3 lightColor = pointLightColor;
    vec3 diffuse =  lightDiffuse * nDotL;
    vec3 specular = lightSpecular * pow(nDotHV, 1.0) * nDotL;
    lightColor += diffuse + specular;

    float attenuation = clamp(1.0 / (lightAttenuation.x + lightAttenuation.y * dist + lightAttenuation.z * dist * dist), 0.0, 1.0);


    gl_FragColor = vec4(vec3(Color * lightColor * attenuation), 1.0);
}

必要に応じて、sencil パスやその他すべての処理を投稿することもできます。

4

2 に答える 2

5

これが少し古いことは知っていますが、多くの調査の結果、すべてが機能していることを知っておいてください! 誰かが同様/同じ問題を抱えている場合は、ここに投稿したかっただけです。

実際、位置マップは完全に間違っていました (まあ、私の照明モデルもそうですが、それは別の話です :))。あなたがすでに言ったように、私は固定パイプライン関数で作業していました (これは本当にばかげていました)。実際の失敗は、「モデルマトリックス」を取得していたことでした

glGetFloatv(GL_MODELVIEW_MATRIX,mat);
glUniformMatrix4fv(worldMatrixLocation, 1, GL_FALSE, mat);

これは実際にはモデルマトリックス * 固定パイプラインのビューマトリックスです。だから私はすべてをカスタムモデルの計算に変更し、出来上がり、位置マップは正しかった. (まあ、固定関数パイプラインを使用して、一致する値を持つカスタム モデル マトリックスをセットアップし、それをモデル マトリックスとしてシェーダーに入力することもできますが、それは単にダーティです)。あなたのおかげで、私は正しい道を歩み、行列の計算やシェーダーなどをより多く理解することができました!

ところで: gbuffer は次のようになりました (textureposition は実際には不要です :)): ここに画像の説明を入力

于 2013-11-01T06:06:06.790 に答える