Anonymous
Странное поведение отображения теней
Сообщение
Anonymous » 18 мар 2024, 07:25
Я пытаюсь реализовать отображение теней с помощью OpenGL и GLSL 120:
ShadowPass.vert
Код: Выделить всё
#version 120
void main()
{
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
ShadowPass.frag
Код: Выделить всё
#version 120
uniform float near_plane;
uniform float far_plane;
void main()
{
float z = gl_FragCoord.z;
float n = near_plane;
float f = far_plane;
float c = (2.0 * n) / (f + n - z * (f - n));
gl_FragDepth = c;
}
RenderPass.vert
Код: Выделить всё
#version 120
varying vec3 position;
varying vec3 normal;
varying vec3 FragPos;
varying vec4 FragPosLightSpace;
uniform mat4 lightSpaceMatrix;
void main()
{
vec4 eyeCoordPos = gl_ModelViewMatrix * gl_Vertex;
position = eyeCoordPos.xyz / eyeCoordPos.w;
normal = normalize(gl_NormalMatrix * gl_Normal);
gl_TexCoord[0] = gl_MultiTexCoord0;
gl_FrontColor = gl_Color;
FragPos = gl_Vertex.xyz;
FragPosLightSpace = lightSpaceMatrix * gl_Vertex;
gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
}
RenderPass.frag
Код: Выделить всё
#version 120
#define USE_INNER_AND_OUTER_CONES
#if defined(USE_INNER_AND_OUTER_CONES)
uniform float cosOuterCone;
uniform float cosInnerCone;
#endif
varying vec3 position;
varying vec3 normal;
uniform bool computeShadows;
uniform sampler2D colorMap;
uniform sampler2D shadowMap;
uniform vec3 lightPos;
varying vec3 FragPos;
varying vec4 FragPosLightSpace;
vec4 ShadowCalculation()
{
vec3 projCoords = FragPosLightSpace.xyz / FragPosLightSpace.w;
projCoords = projCoords * 0.5 + 0.5; // Bias Matrix...
float closestDepth = texture2D(shadowMap, projCoords.xy).r;
float z = projCoords.z;
float n = 1.0;
float f = 1000.0;
float currentDepth = (2.0 * n) / (f + n - z * (f - n));
vec3 shadow = vec3(1.0, 1.0, 1.0);
float bias = 0.0005;
if(closestDepth + bias < currentDepth)
{
shadow = vec3(0.5, 0.5, 0.5); // Shadow color
}
return vec4(shadow, 1.0);
}
void main()
{
vec3 l = gl_LightSource[0].position.xyz - position;
float d = length(l);
float atten = 1.0 / (gl_LightSource[0].constantAttenuation +
gl_LightSource[0].linearAttenuation * d +
gl_LightSource[0].quadraticAttenuation * d * d);
l = normalize(l);
float spotDot = dot(-l, normalize(gl_LightSource[0].spotDirection));
#if defined(USE_INNER_AND_OUTER_CONES)
float spotEffect = smoothstep(cosOuterCone, cosInnerCone, spotDot);
#else
float spotEffect = (spotDot < gl_LightSource[0].spotCosCutoff)
? 0.0 : pow(spotDot, gl_LightSource[0].spotExponent);
#endif
atten *= spotEffect;
vec3 n = normalize(normal);
vec3 v = normalize(-position);
vec3 h = normalize(l + v);
float nDotL = max(0.0, dot(n, l));
float nDotH = max(0.0, dot(n, h));
float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess);
vec4 ambient = gl_FrontLightProduct[0].ambient * atten;
vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL * atten;
vec4 specular = gl_FrontLightProduct[0].specular * power * atten;
vec4 lightColor = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular;
vec4 finalColor = vec4(0);
if (computeShadows)
{
vec4 shadow = ShadowCalculation();
finalColor = shadow * texture2D(colorMap, gl_TexCoord[0].st) * lightColor;
}
else
{
finalColor = lightColor * texture2D(colorMap, gl_TexCoord[0].st);
}
gl_FragColor = finalColor;
}
Сцена рендеринга приложения
Код: Выделить всё
glBindFramebuffer(GL_FRAMEBUFFER, shadowMapFBO);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_DEPTH_BUFFER_BIT);
pShaderMgr->bind(0);
glUniform1f(glGetUniformLocation(pShaderMgr->id(0), "near_plane"), near_plane);
glUniform1f(glGetUniformLocation(pShaderMgr->id(0), "far_plane"), far_plane);
glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluPerspective(45.0f, static_cast(SHADOW_WIDTH) / static_cast(SHADOW_HEIGHT), near_plane, far_plane);
//glOrtho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
// OR
lightProjection = glm::perspective(glm::radians(45.0f), static_cast(SHADOW_WIDTH) / static_cast(SHADOW_HEIGHT), near_plane, far_plane);
//lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane);
glLoadMatrixf((float*)&lightProjection);
//glGetFloatv(GL_PROJECTION_MATRIX, (float*)&lightProjection);
lightView = glm::lookAt(glm::vec3(LightPosition[0], LightPosition[1], LightPosition[2]),
glm::vec3(LightDirection[0], LightDirection[1], LightDirection[2]),
glm::vec3(0.0, 1.0, 0.0));
lightSpaceMatrix = /*biasMatrix*/ lightProjection * lightView;
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glLoadMatrixf((float*)&lightView);
glPushMatrix();
glTranslatef(0.0f, 1.0f, 0.0f);
DrawCubeVBO();
glPopMatrix();
glPushMatrix();
glTranslatef(-1.0f, 4.0f, 1.0f);
DrawCubeVBO();
glPopMatrix();
glBindFramebuffer(GL_FRAMEBUFFER, 0);
pShaderMgr->unbind();
/////////////////////////////////// COLOR BUFFER /////////////////////////////////////////////////////////
glViewport(0, 0, WIDTH, HEIGHT);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Limpa a tela e o Depth Buffer
glLoadIdentity(); // Inicializa a Modelview Matrix Atual
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
//gluPerspective(45.0f, static_cast(WIDTH) / static_cast(HEIGHT), near_plane, far_plane);
// OR
glm::mat4 camProjection = glm::perspective(glm::radians(45.0f), static_cast(WIDTH) / static_cast(HEIGHT), near_plane, far_plane);
glLoadMatrixf((float*)&camProjection);
pCamera->setView();
// Desenha os eixos do sistema cartesiano
DrawAxis();
// Modo FILL ou WIREFRAME (pressione barra de espaço)
if (bIsWireframe)
glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
else
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// DESENHA OS OBJETOS DA CENA (INÍCIO)
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
pShaderMgr->bind(1);
glUniform1i(glGetUniformLocation(pShaderMgr->id(1), "colorMap"), 0);
glUniform1i(glGetUniformLocation(pShaderMgr->id(1), "shadowMap"), 1);
glUniform1i(glGetUniformLocation(pShaderMgr->id(1), "computeShadows"), true);
glUniform1f(glGetUniformLocation(pShaderMgr->id(1), "cosInnerCone"), g_cosInnerCone);
glUniform1f(glGetUniformLocation(pShaderMgr->id(1), "cosOuterCone"), g_cosOuterCone);
glUniform3f(glGetUniformLocation(pShaderMgr->id(1), "lightPos"), LightPosition[0], LightPosition[1], LightPosition[2]);
glUniformMatrix4fv(glGetUniformLocation(pShaderMgr->id(1), "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix));
// Setup lighting and shaders.
glPushAttrib(GL_LIGHTING_BIT);
glEnable(GL_LIGHTING);
glEnable(GL_LIGHT0);
glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, SPOT_OUTER_CONE);
glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0f);
glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, LightDirection);
glLightfv(GL_LIGHT0, GL_POSITION, LightPosition);
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
pTextures->ApplyTexture(0);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, shadowMap);
// Draw Cubes
glPushMatrix();
glTranslatef(0.0f, 1.0f, 0.0f);
DrawCubeVBO();
glPopMatrix();
glPushMatrix();
glTranslatef(-1.0f, 4.0f, 1.0f);
DrawCubeVBO();
glPopMatrix();
// Draw Ground
glActiveTexture(GL_TEXTURE0);
pTextures->ApplyTexture(2);
glUniform1i(glGetUniformLocation(pShaderMgr->id(1), "computeShadows"), true);
glPushMatrix();
glTranslatef(0.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glNormal3f(0.0f, 1.0f, 0.0f);
glTexCoord2d(0.0f, 0.0f); glVertex3f(-20.0f, 0.0f, 20.0f);
glTexCoord2d(0.0f, 1.0f); glVertex3f(20.0f, 0.0f, 20.0f);
glTexCoord2d(1.0f, 1.0f); glVertex3f(20.0f, 0.0f, -20.0f);
glTexCoord2d(1.0f, 0.0f); glVertex3f(-20.0f, 0.0f, -20.0f);
glEnd();
glPopMatrix();
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
pShaderMgr->unbind();
glDisable(GL_LIGHT0);
glDisable(GL_LIGHTING);
glPopAttrib();
Проблема заключается в сопоставлении карты теней с объектами сцены. Результат можно увидеть на этом изображении:
< /p>
Тень отображается неправильно. Похоже, что это повторяется в объектах.
Я считаю, что это проблема при рендеринге кубов в функции рендеринга. Кто-нибудь может подсказать, почему на кубиках не правильно рассчитываются тени? Верх кубиков должен быть на свету...
Подробнее здесь:
https://stackoverflow.com/questions/781 ... -behaviour
1710735912
Anonymous
Я пытаюсь реализовать отображение теней с помощью OpenGL и GLSL 120: ShadowPass.vert [code]#version 120 void main() { gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } [/code] ShadowPass.frag [code]#version 120 uniform float near_plane; uniform float far_plane; void main() { float z = gl_FragCoord.z; float n = near_plane; float f = far_plane; float c = (2.0 * n) / (f + n - z * (f - n)); gl_FragDepth = c; } [/code] RenderPass.vert [code]#version 120 varying vec3 position; varying vec3 normal; varying vec3 FragPos; varying vec4 FragPosLightSpace; uniform mat4 lightSpaceMatrix; void main() { vec4 eyeCoordPos = gl_ModelViewMatrix * gl_Vertex; position = eyeCoordPos.xyz / eyeCoordPos.w; normal = normalize(gl_NormalMatrix * gl_Normal); gl_TexCoord[0] = gl_MultiTexCoord0; gl_FrontColor = gl_Color; FragPos = gl_Vertex.xyz; FragPosLightSpace = lightSpaceMatrix * gl_Vertex; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } [/code] RenderPass.frag [code]#version 120 #define USE_INNER_AND_OUTER_CONES #if defined(USE_INNER_AND_OUTER_CONES) uniform float cosOuterCone; uniform float cosInnerCone; #endif varying vec3 position; varying vec3 normal; uniform bool computeShadows; uniform sampler2D colorMap; uniform sampler2D shadowMap; uniform vec3 lightPos; varying vec3 FragPos; varying vec4 FragPosLightSpace; vec4 ShadowCalculation() { vec3 projCoords = FragPosLightSpace.xyz / FragPosLightSpace.w; projCoords = projCoords * 0.5 + 0.5; // Bias Matrix... float closestDepth = texture2D(shadowMap, projCoords.xy).r; float z = projCoords.z; float n = 1.0; float f = 1000.0; float currentDepth = (2.0 * n) / (f + n - z * (f - n)); vec3 shadow = vec3(1.0, 1.0, 1.0); float bias = 0.0005; if(closestDepth + bias < currentDepth) { shadow = vec3(0.5, 0.5, 0.5); // Shadow color } return vec4(shadow, 1.0); } void main() { vec3 l = gl_LightSource[0].position.xyz - position; float d = length(l); float atten = 1.0 / (gl_LightSource[0].constantAttenuation + gl_LightSource[0].linearAttenuation * d + gl_LightSource[0].quadraticAttenuation * d * d); l = normalize(l); float spotDot = dot(-l, normalize(gl_LightSource[0].spotDirection)); #if defined(USE_INNER_AND_OUTER_CONES) float spotEffect = smoothstep(cosOuterCone, cosInnerCone, spotDot); #else float spotEffect = (spotDot < gl_LightSource[0].spotCosCutoff) ? 0.0 : pow(spotDot, gl_LightSource[0].spotExponent); #endif atten *= spotEffect; vec3 n = normalize(normal); vec3 v = normalize(-position); vec3 h = normalize(l + v); float nDotL = max(0.0, dot(n, l)); float nDotH = max(0.0, dot(n, h)); float power = (nDotL == 0.0) ? 0.0 : pow(nDotH, gl_FrontMaterial.shininess); vec4 ambient = gl_FrontLightProduct[0].ambient * atten; vec4 diffuse = gl_FrontLightProduct[0].diffuse * nDotL * atten; vec4 specular = gl_FrontLightProduct[0].specular * power * atten; vec4 lightColor = gl_FrontLightModelProduct.sceneColor + ambient + diffuse + specular; vec4 finalColor = vec4(0); if (computeShadows) { vec4 shadow = ShadowCalculation(); finalColor = shadow * texture2D(colorMap, gl_TexCoord[0].st) * lightColor; } else { finalColor = lightColor * texture2D(colorMap, gl_TexCoord[0].st); } gl_FragColor = finalColor; } [/code] Сцена рендеринга приложения [code]glBindFramebuffer(GL_FRAMEBUFFER, shadowMapFBO); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_DEPTH_BUFFER_BIT); pShaderMgr->bind(0); glUniform1f(glGetUniformLocation(pShaderMgr->id(0), "near_plane"), near_plane); glUniform1f(glGetUniformLocation(pShaderMgr->id(0), "far_plane"), far_plane); glViewport(0, 0, SHADOW_WIDTH, SHADOW_HEIGHT); glMatrixMode(GL_PROJECTION); glLoadIdentity(); //gluPerspective(45.0f, static_cast(SHADOW_WIDTH) / static_cast(SHADOW_HEIGHT), near_plane, far_plane); //glOrtho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); // OR lightProjection = glm::perspective(glm::radians(45.0f), static_cast(SHADOW_WIDTH) / static_cast(SHADOW_HEIGHT), near_plane, far_plane); //lightProjection = glm::ortho(-10.0f, 10.0f, -10.0f, 10.0f, near_plane, far_plane); glLoadMatrixf((float*)&lightProjection); //glGetFloatv(GL_PROJECTION_MATRIX, (float*)&lightProjection); lightView = glm::lookAt(glm::vec3(LightPosition[0], LightPosition[1], LightPosition[2]), glm::vec3(LightDirection[0], LightDirection[1], LightDirection[2]), glm::vec3(0.0, 1.0, 0.0)); lightSpaceMatrix = /*biasMatrix*/ lightProjection * lightView; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glLoadMatrixf((float*)&lightView); glPushMatrix(); glTranslatef(0.0f, 1.0f, 0.0f); DrawCubeVBO(); glPopMatrix(); glPushMatrix(); glTranslatef(-1.0f, 4.0f, 1.0f); DrawCubeVBO(); glPopMatrix(); glBindFramebuffer(GL_FRAMEBUFFER, 0); pShaderMgr->unbind(); /////////////////////////////////// COLOR BUFFER ///////////////////////////////////////////////////////// glViewport(0, 0, WIDTH, HEIGHT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Limpa a tela e o Depth Buffer glLoadIdentity(); // Inicializa a Modelview Matrix Atual glMatrixMode(GL_PROJECTION); glLoadIdentity(); //gluPerspective(45.0f, static_cast(WIDTH) / static_cast(HEIGHT), near_plane, far_plane); // OR glm::mat4 camProjection = glm::perspective(glm::radians(45.0f), static_cast(WIDTH) / static_cast(HEIGHT), near_plane, far_plane); glLoadMatrixf((float*)&camProjection); pCamera->setView(); // Desenha os eixos do sistema cartesiano DrawAxis(); // Modo FILL ou WIREFRAME (pressione barra de espaço) if (bIsWireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); else glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // DESENHA OS OBJETOS DA CENA (INÍCIO) ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// glColor4f(1.0f, 1.0f, 1.0f, 1.0f); pShaderMgr->bind(1); glUniform1i(glGetUniformLocation(pShaderMgr->id(1), "colorMap"), 0); glUniform1i(glGetUniformLocation(pShaderMgr->id(1), "shadowMap"), 1); glUniform1i(glGetUniformLocation(pShaderMgr->id(1), "computeShadows"), true); glUniform1f(glGetUniformLocation(pShaderMgr->id(1), "cosInnerCone"), g_cosInnerCone); glUniform1f(glGetUniformLocation(pShaderMgr->id(1), "cosOuterCone"), g_cosOuterCone); glUniform3f(glGetUniformLocation(pShaderMgr->id(1), "lightPos"), LightPosition[0], LightPosition[1], LightPosition[2]); glUniformMatrix4fv(glGetUniformLocation(pShaderMgr->id(1), "lightSpaceMatrix"), 1, GL_FALSE, glm::value_ptr(lightSpaceMatrix)); // Setup lighting and shaders. glPushAttrib(GL_LIGHTING_BIT); glEnable(GL_LIGHTING); glEnable(GL_LIGHT0); glLightf(GL_LIGHT0, GL_SPOT_CUTOFF, SPOT_OUTER_CONE); glLightf(GL_LIGHT0, GL_SPOT_EXPONENT, 2.0f); glLightfv(GL_LIGHT0, GL_SPOT_DIRECTION, LightDirection); glLightfv(GL_LIGHT0, GL_POSITION, LightPosition); glActiveTexture(GL_TEXTURE0); glEnable(GL_TEXTURE_2D); pTextures->ApplyTexture(0); glActiveTexture(GL_TEXTURE1); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, shadowMap); // Draw Cubes glPushMatrix(); glTranslatef(0.0f, 1.0f, 0.0f); DrawCubeVBO(); glPopMatrix(); glPushMatrix(); glTranslatef(-1.0f, 4.0f, 1.0f); DrawCubeVBO(); glPopMatrix(); // Draw Ground glActiveTexture(GL_TEXTURE0); pTextures->ApplyTexture(2); glUniform1i(glGetUniformLocation(pShaderMgr->id(1), "computeShadows"), true); glPushMatrix(); glTranslatef(0.0f, 0.0f, 0.0f); glBegin(GL_QUADS); glNormal3f(0.0f, 1.0f, 0.0f); glTexCoord2d(0.0f, 0.0f); glVertex3f(-20.0f, 0.0f, 20.0f); glTexCoord2d(0.0f, 1.0f); glVertex3f(20.0f, 0.0f, 20.0f); glTexCoord2d(1.0f, 1.0f); glVertex3f(20.0f, 0.0f, -20.0f); glTexCoord2d(1.0f, 0.0f); glVertex3f(-20.0f, 0.0f, -20.0f); glEnd(); glPopMatrix(); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, 0); glDisable(GL_TEXTURE_2D); pShaderMgr->unbind(); glDisable(GL_LIGHT0); glDisable(GL_LIGHTING); glPopAttrib(); [/code] Проблема заключается в сопоставлении карты теней с объектами сцены. Результат можно увидеть на этом изображении: [img]https://i.stack.imgur.com/EZsr6.jpg[/img] < /p> Тень отображается неправильно. Похоже, что это повторяется в объектах. Я считаю, что это проблема при рендеринге кубов в функции рендеринга. Кто-нибудь может подсказать, почему на кубиках не правильно рассчитываются тени? Верх кубиков должен быть на свету... Подробнее здесь: [url]https://stackoverflow.com/questions/78177764/shadow-mapping-strange-behaviour[/url]