2013-10-09 4 views
1

OpenGL 및 GLSL에 대한 경험이 상당히 있습니다. 내 엔진의 경우 지연 조명을 구현하고 싶었지만 사소한 작업이 아니었다는 것을 알고있었습니다. 몇 시간 후 나는 대부분 일하는 것을 얻을 수있었습니다. 다음은 렌더링 한 모든 버퍼의 스크린 샷입니다.지연 렌더링이 예상대로 작동하지 않습니다.

왼쪽 위가 법선이고, 오른쪽 위가 알베도이고, 왼쪽 하단이 위치이고 오른쪽 아래가 최종 렌더링입니다. (단 하나의 라이트 만 렌더링됩니다.) 저는 모든 것을 프레임 버퍼에 렌더링하기 위해 다양한 셰이더를 사용합니다. 이전에 렌더링 렌더링 쉐이더를 사용했습니다. 같은 결과를 얻으려면 버텍스 쉐이더의 동일한 데이터를 사용하여 여러 버퍼를 렌더링하십시오. 광원은 내 전방 렌더러와 달리 내 카메라의 위치에 따라 이동하고 변경됩니다. 알베도 I에 대한

varying vec4 pos; 
void main(void) 
{ 
    gl_Position =gl_ModelViewProjectionMatrix*gl_Vertex; 
    pos = gl_ModelViewMatrix*gl_Vertex; 
} 

일반 쉐이더

varying vec3 normal; 
void main(void) 
{ 
    gl_Position =gl_ModelViewProjectionMatrix*gl_Vertex; 
    normal = normalize(gl_NormalMatrix*gl_Normal); 
} 

다음은 정점 셰이더에 대한 코드

위치 쉐이더 (조각 사람은 단지 그들이 정점 하나를 가지고 픽셀을 렌더링)입니다 그냥 OpenGL의 일반 쉐이더를 사용하고 텍스처를 바인딩하십시오. 여기

화면을 통해 쿼드로 렌더링되는 마지막 빛 쉐이더입니다 :이 다른 곳에서 참조하는 기능을 많이 가지고

uniform sampler2D positionMap; 
uniform sampler2D normalMap; 
uniform sampler2D albedoMap; 
varying vec2 texcoord; 
uniform mat4 matrix; 
void main() 
{ 
    vec3 position = vec3(texture2D(positionMap,texcoord)); 
    vec3 normal = vec3(texture2D(normalMap,texcoord)); 

    vec3 L = normalize(gl_LightSource[0].position.xyz - position); 
    float l = length(L)/5.0; 
    float att = 1.0/(l*l+l); 

    //render sun light 
    vec4 diffuselight = max(dot(normal,L), 0.0)*vec4(att,att,att,att); 
    diffuselight = clamp(diffuselight, 0.0, 1.0)*2.0; 
    vec4 amb = vec4(.2,.2,.2,0); 

    vec4 texture = texture2D(albedoMap,texcoord); 

    gl_FragColor = ((diffuselight)+amb)*texture; 

} 

,하지만 난 당신이에서 일반 기초를 얻을 수 있다고 생각 사진과 코드. 다음은 주 렌더링 함수입니다.

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

//render skybox 
glLoadIdentity(); 
renderSkybox(); 
//skybox.renderObject(); 
glLoadIdentity(); 
renderViewModel(); 


renderCamera(); 
glMatrixMode(GL_MODELVIEW); 
GLfloat position[] = {-Lighting.x,-Lighting.y,-Lighting.z,1}; 
glLightfv(GL_LIGHT0, GL_POSITION, position); 
glDisable(GL_LIGHTING); 

glm::mat4 modelView,projection,final; 
glGetFloatv(GL_MODELVIEW_MATRIX, &modelView[0][0]); 
glGetFloatv(GL_PROJECTION_MATRIX, &projection[0][0]); 
final=modelView*projection; 

Lighting.setupDepthImage(); 
glLoadIdentity(); 

for (int i = 0; i < objects.size(); i++) 
{ 
    objects[i].renderObjectForDepth(); 
} 
    Lighting.finishDepthImage(); 

//render the 3 buffers 

//normal buffer 
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Normal.frameBuffer); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
for (int i = 0; i < objects.size(); i++) 
{ 
    objects[i].renderObjectWithProgram(Lighting.normalShader); 
} 
//albedo 
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Albedo.frameBuffer); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
for (int i = 0; i < objects.size(); i++) 
{ 
    objects[i].renderObjectWithProgram(0); 
} 
//position 
glBindFramebuffer(GL_FRAMEBUFFER, Lighting.Position.frameBuffer); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
for (int i = 0; i < objects.size(); i++) 
{ 
    objects[i].renderObjectWithProgram(Lighting.positionShader); 
} 
//go back to rendering directly to the screen 
glBindFramebuffer(GL_FRAMEBUFFER, 0); 


renderCamera(); 
glTranslatef(-test.position.x, test.position.y, -test.position.z); 
test.updateParticle(1); 

//render the buffers for debugging 
renderViewModel(); 
glMatrixMode(GL_PROJECTION); 
glLoadIdentity(); 
glOrtho(0, 1280, 800, 0, -1, 1); 
glMatrixMode(GL_MODELVIEW); 
glLoadIdentity(); 

//render the full screen quad for the sun 
glUseProgram(Lighting.sunShader); 

glUniform1i(glGetUniformLocation(Lighting.sunShader,"normalMap"),0); 
glUniform1i(glGetUniformLocation(Lighting.sunShader,"albedoMap"),1); 
glUniform1i(glGetUniformLocation(Lighting.sunShader,"positionMap"),2); 
glUniformMatrix4fv(glGetUniformLocation(Lighting.sunShader, "matrix"), 1, GL_FALSE, &final[0][0]); 

glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, Lighting.Normal.texture); 
glActiveTexture(GL_TEXTURE1); 
glBindTexture(GL_TEXTURE_2D, Lighting.Albedo.texture); 
glActiveTexture(GL_TEXTURE2); 
glBindTexture(GL_TEXTURE_2D, Lighting.Position.texture); 




glBindFramebuffer(GL_FRAMEBUFFER, Lighting.debugFinal.frameBuffer); 
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
glBegin(GL_QUADS); 
glTexCoord2f(0, 1); 
glVertex2f(0, 0); 
glTexCoord2f(1, 1); 
glVertex2f(1280, 0); 
glTexCoord2f(1, 0); 
glVertex2f(1280, 800); 
glTexCoord2f(0, 0); 
glVertex2f(0, 800); 
glEnd(); 

glBindFramebuffer(GL_FRAMEBUFFER, 0); 
glActiveTexture(GL_TEXTURE0); 
glBindTexture(GL_TEXTURE_2D, 0); 

glUseProgram(0); 
//normals 
glBindTexture(GL_TEXTURE_2D,Lighting.Normal.texture); 
glBegin(GL_QUADS); 
glTexCoord2f(0, 1); 
glVertex2f(0, 0); 
glTexCoord2f(1, 1); 
glVertex2f(640, 0); 
glTexCoord2f(1, 0); 
glVertex2f(640, 400); 
glTexCoord2f(0, 0); 
glVertex2f(0, 400); 
glEnd(); 
//albedo 
glBindTexture(GL_TEXTURE_2D,Lighting.Albedo.texture); 
glBegin(GL_QUADS); 
glTexCoord2f(0, 1); 
glVertex2f(640, 0); 
glTexCoord2f(1, 1); 
glVertex2f(1280, 0); 
glTexCoord2f(1, 0); 
glVertex2f(1280, 400); 
glTexCoord2f(0, 0); 
glVertex2f(640, 400); 
glEnd(); 
//position 
glBindTexture(GL_TEXTURE_2D,Lighting.Position.texture); 
glBegin(GL_QUADS); 
glTexCoord2f(0, 1); 
glVertex2f(0, 400); 
glTexCoord2f(1, 1); 
glVertex2f(640, 400); 
glTexCoord2f(1, 0); 
glVertex2f(640, 800); 
glTexCoord2f(0, 0); 
glVertex2f(0, 800); 
glEnd(); 
//final image 
glBindTexture(GL_TEXTURE_2D,Lighting.debugFinal.texture); 
glBegin(GL_QUADS); 
glTexCoord2f(0, 1); 
glVertex2f(640, 400); 
glTexCoord2f(1, 1); 
glVertex2f(1280, 400); 
glTexCoord2f(1, 0); 
glVertex2f(1280, 800); 
glTexCoord2f(0, 0); 
glVertex2f(640, 800); 
glEnd(); 
View3D(); 



SDL_GL_SwapWindow(window); 
glLoadIdentity(); 

여기에는 관련없는 몇 가지 사항이 있지만 무시해보십시오. 보시다시피 GLSL의 기본 메소드를 사용하여 라이트의 위치를 ​​얻습니다. 나는 정사영의 관점에서 볼 때, 무언가가 빛의 위치와 관련이 있다고 생각합니다. 이것이 문제가 될 수 있습니까? 아니면 법칙 계산 등 다른 문제가 있습니까?

+0

'# version' 지시어는 어디에 있습니까? – genpfault

+0

@genpfault 나는 그들을 가지고 있지 못해서 아무런 문제가 없었습니다 ... – BlueSpud

+2

깊이 버퍼에서 world-space/view-space 위치를 재구성 해보십시오. 적절한 정밀도 (예 : 구성 요소 당 32 비트 FP)로 자체 버퍼에 위치를 저장하면 내일은 없기 때문에 메모리 대역폭을 사용할 수 있습니다. 이 문제에 대해 G-Buffers가 어딘가에 명확하게 저장되어있는 좌표 공간을 정의하면 전체 문제 일 수 있습니다. 필자는 사용하는 다양한 사후 처리 효과와 대부분의 빅 네임 엔진 (예 : Unreal Engine 4, CryTek 3 등)에서 성능을 위해 우주 공간 버퍼를 선호합니다. –

답변

1

아마도 사람들은이 기능을 유용하게 사용할 수 없지만 내 문제는 해결했습니다. 나는 셰이더에서 조명을 위해 정규 OpenGL 조명을 사용하고있었습니다. 위치를 설정할 때 w 값을 1로 만들었습니다. 방향키는 점 광원이 아니므로 빛이 움직이는 행동을하게됩니다.

측면에서 G 버퍼를 개선하기 위해 몇 가지 다른 사항뿐만 아니라 깊이 버퍼에서 재구성 할 위치를 변경하지 않았습니다.

+1

아, 네. 나는 이것에 대해 생각하지 않았다는 것에 놀랐습니다. 위치 벡터는 항상 4 번째 구성 요소 (일반적으로 1.0)를 가지므로 4x4 행렬 곱셈은 변환과 같은 연산에 적합하게 작동해야합니다. 방향 벡터는 4x4 행렬로 곱해질 때 w가 암시 적으로 0.0이라는 이해와 함께 3D가 될 수 있습니다. 왜 포인트 라이트 (위치)가 w = 1.0인지, 방향 라이트는 w = 0.0인지를 완벽하게 설명합니다. 정점 pos를 지정할 때주의하십시오. 단지 세 좌표를 사용하는 VBO에서, 'vec4' 1.0이 자동으로 w에 할당 될 때 정점 셰이더에서 사용할 때. –

관련 문제