Я использую OpenGL 4.0, GLSL 4.0, а не GLEW или подобное, а не GLU или подобное, а не GLUT или подобное. OpenCL или CUDA также используются, но они не участвуют в этом случае.Двойное параболоидное отображение теней
Я пытался решить свою проблему в течение нескольких недель без успеха, и теперь я надеюсь, что кто-то, у кого есть опыт с двойным параболоидным теневым отображением, может дать мне совет. Давайте идти прямо к проблеме и проверить некоторые фотографии (рисунок 1):
Изображение 1 содержит некоторые цветные стрелки мне нужно объяснить. Красные стрелки показывают только правильные тени, которые мы должны видеть. Другие стрелки указывают на ошибки затенения: желтые стрелки показывают пятна, вызванные тесселяцией, возможно, и синие стрелки, но их расположение находится на границе передних/задних полушарий. И зеленая стрелка указывает на пилообразный рисунок, который не должен существовать (он отсутствует в примерах, которые мы видим в последнее время). Теперь важно заметить, что картина выше была вычислена с помощью следующей строки кода (код 1):
"swap.z=-sign(swap.z)*swap.z;\n" //mostly right results in the main project, but wrong way
Эта строка кода находится в программе GLSL шейдеров, и это один из четырех кандидатов, которых я был пытаясь без успеха в основном проекте, откуда сделаны снимки. Однако, как мы увидим, код 4 работает в отдельной тестовой программе. Код 1 на самом деле совершенно неправильный способ сделать DPSM, но это единственный способ, которым мой основной проект получает теневое изображение. Далее мы рассмотрим и та же сцена вычисляется немного по-другому, но все-таки неправильный код линии (рисунок 2 и код 2):
"swap.z=sign(swap.z)*swap.z;\n" //almost dark picture, wrong way
Опять мы смотрим на ту же сцену, но теперь мы используем совершенно разные , ортодоксальный код линии (рисунок 3 и код 3):
"swap.z=-(teDistance-n)/(f-n);\n" //lightning is mainly working but no shadows, should be the right way
Наконец мы смотрим на сцену, вычисленный с помощью кода линия, которая работает (почти) в примерах мы видим в последнее время (фото 4 и код 4):
"swap.z=(teDistance-n)/(f-n);\n" //almost dark picture, doesn't work in the main project, but works in the test program, right way
Если кто-то подозревает, что артефакты видели в изображениях выше, из-за явления, называемого «теневого акне «, ну нет, я думаю, что это не так. Ниже картина, которая имеет тень акне шаблон я намеренно сделал, установив SHADOW_EPSILON = 0.000005f
и выключение размытости (изображение 5):
На данный момент мне нужно сказать, что я запустить программу на двух отдельные ноутбуки Windows 7.1, один с nVIDIA GeForce GT 525M и еще один AMD Radeon R6. Результаты были идентичными. Компилятор - это Visual Studio 2010. Мне кажется, что это проблема, связанная с OpenGL.
Чтобы решить эту проблему, я написал отдельную небольшую тестовую программу и, наконец, обработал теневое отображение. Насколько я вижу, тестовая программа работает практически так же, как и программа, которая делала снимки 1-5, но нет оптимизаций, и количество матричных умножений было перенесено с хоста на шейдеры. Ниже приведены соответствующие части источника тестовой программы.Шейдеры первый:
static const char *vertex1=
"#version 400 core\n"
"layout (location=1) in vec3 vertexLocation;\n"
"out vec3 vPosition;\n"
"void main() {\n"
"vPosition=vertexLocation;\n"
"}\0";
static const char *tessIn1=
"#version 400 core\n"
"layout (vertices=3) out;\n"
"in vec3 vPosition[];\n"
"out vec3 tcPosition[];\n"
"void main() {\n"
"tcPosition[gl_InvocationID]=vPosition[gl_InvocationID];\n"
"if (gl_InvocationID==0) {\n"
"gl_TessLevelOuter[0]=max(distance(vPosition[1], vPosition[2]), 1.0);\n"
"gl_TessLevelOuter[1]=max(distance(vPosition[2], vPosition[0]), 1.0);\n"
"gl_TessLevelOuter[2]=max(distance(vPosition[0], vPosition[1]), 1.0);\n"
"gl_TessLevelInner[0]=max(0.33*(gl_TessLevelOuter[0]+gl_TessLevelOuter[1]+gl_TessLevelOuter[2]), 1.0);\n"
"}\n"
"}\0";
static const char* tessOut1=
"#version 400 core\n"
"layout(triangles, equal_spacing, ccw) in;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 lightOrientation;\n"
"in vec3 tcPosition[];\n"
"out float teDistance;\n"
"out float teClip;\n"
"const float n=0.5;\n"
"const float f=20000.0;\n"
"void main() {\n"
"vec3 accum=vec3(0.0);\n"
"accum=accum+gl_TessCoord.x*tcPosition[0];\n"
"accum=accum+gl_TessCoord.y*tcPosition[1];\n"
"accum=accum+gl_TessCoord.z*tcPosition[2];\n"
// Transform position to the paraboloid's view space
"vec4 swap=lightOrientation*model*vec4(accum, 1.0);\n"
//store the distance and other variables
"teDistance=abs(swap.z);\n"
"teClip=swap.z;\n"
//calculate and set X and Y coordinates
"swap.xyz=normalize(swap.xyz);\n"
"if (swap.z<=0.0) {\n"
"swap.xy=swap.xy/(1.0-swap.z);\n"
"} else {\n"
"swap.xy=swap.xy/(1.0+swap.z);\n"
"}\n"
//calculate and set Z and W coordinates
// "swap.z=-sign(swap.z)*swap.z;\n" //Wrong way
// "swap.z=sign(swap.z)*swap.z;\n" //Wrong way
// "swap.z=-(teDistance-n)/(f-n);\n" //Wrong way
"swap.z=(teDistance-n)/(f-n);\n" //Right way
"swap.w=1.0;\n"
"gl_Position=swap;\n"
"}\0";
static const char* geometry1=
"#version 400 core\n"
"layout(triangles) in;\n"
"layout(triangle_strip, max_vertices=3) out;\n"
"in float teDistance[];\n"
"in float teClip[];\n"
"out float gDistance;\n"
"void main() {\n"
"for (int i=0; i<3; i++) {\n"
"gDistance=teDistance[i];\n"
"if (teClip[i]<=0.0) {\n"
"gl_Layer=0;\n"
"} else {\n"
"gl_Layer=1;\n"
"}\n"
"gl_Position=gl_in[i].gl_Position;\n"
"EmitVertex();\n"
"}\n"
"EndPrimitive();\n"
"}\0";
static const char* fragment1=
"#version 400 core\n"
"in float gDistance;\n"
"out vec2 fragmentVari;\n"
"void main() {\n"
"fragmentVari=vec2(gDistance, gDistance*gDistance);\n"
"}\0";
const char *vertex2=
"#version 400 core\n"
"layout (location=1) in vec3 vertexPosition;\n"
"layout (location=2) in vec2 vertexTexCoord;\n"
"layout (location=3) in vec3 vertexNormal;\n"
"const float n=0.5;\n"
"const float f=20000.0;\n"
"uniform vec4 colour;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 normal;\n"
"uniform mat4 projection;\n"
"uniform mat4 lightOrientation;\n"
"out vec2 texKoord;\n"
"out vec3 pointNormal;\n"
"out vec3 point;\n"
"out vec4 color;\n"
"out vec4 vOriginPoint;\n"
"void main() {\n"
"texKoord=vertexTexCoord;\n"
"pointNormal=normalize(vec3(normal*vec4(vertexNormal, 1.0)));\n"
"point=vec3(model*vec4(vertexPosition, 1.0));\n"
"color=colour;\n"
"vOriginPoint=vec4(vertexPosition, 1.0);\n"
"gl_Position=projection*view*model*vec4(vertexPosition, 1.0);\n"
"}\0";
const char *fragment2=
"#version 400 core\n"
"uniform sampler2DArray tex1;\n"
"uniform vec4 colour;\n"
"uniform mat4 model;\n"
"uniform mat4 view;\n"
"uniform mat4 normal;\n"
"uniform mat4 projection;\n"
"uniform mat4 lightOrientation;\n"
"in vec2 texKoord;\n"
"in vec3 pointNormal;\n"
"in vec3 point;\n"
"in vec4 color;\n"
"in vec4 vOriginPoint;\n"
"out vec4 fragmentColor;\n"
"const float SHADOW_EPSILON = 0.05f;\n"
"const vec3 Ka=vec3(0.05, 0.05, 0.05);\n" //Ambient reflectivity
"const vec3 Kd=vec3(1.0, 1.0, 1.0);\n" //Diffuse reflectivity
"const float At=0.4;\n" //Light attenuation
"vec3 ads(in vec3 position, in vec3 normal) {\n"
"vec3 l=vec3(lightOrientation*model*vOriginPoint);\n"
"vec3 s=normalize(l - position);\n"
"vec3 intensity=vec3(0.5, 0.5, 0.5)*10.0;\n"
"float attenuation=1.0/(1.0+At*max(length(l), 1.0));\n"
"intensity=intensity*attenuation*Kd*abs(dot(s, normal));\n"
"return intensity;\n"
"}\n"
"float drawShadow() {\n"
"vec3 texKoord;\n"
"vec4 textureDepth;\n"
"vec4 originPoint=vec4(lightOrientation*model*vOriginPoint);\n"
"float distance=abs(originPoint.z);\n"
"vec3 normalized=normalize(originPoint.xyz);\n"
"if (normalized.z<=0.0) {\n"
"texKoord.xy=normalized.xy/(1.0-normalized.z);\n"
"texKoord.xy=0.5*texKoord.xy+0.5;\n"
"texKoord.z=0.0;\n"
"textureDepth=texture(tex1, texKoord);\n"
"} else {\n"
"texKoord.xy=normalized.xy/(1.0+normalized.z);\n"
"texKoord.xy=0.5*texKoord.xy+0.5;\n"
"texKoord.z=1.0;\n"
"textureDepth=texture(tex1, texKoord);\n"
"}\n"
"if (textureDepth.x+SHADOW_EPSILON>=distance) {\n"
"return 1.0;\n"
"} else {\n"
"return 0.0;\n"
"}\n"
"}\n"
"void main() {\n"
"vec4 lightning=vec4(Ka, 1.0);\n"
"swap2=swap2*drawShadow();\n"
"lightning=lightning+swap2;\n"
"fragmentColor=color*lightning;\n"
"}\0";
const char *vertexLight=
"#version 400 core\n"
"layout (location=1) in vec3 vertexPosition;\n"
"uniform mat4 view;\n"
"uniform mat4 projection;\n"
"uniform mat4 lightOrientation;\n"
"void main() {\n"
"gl_Position=projection*view*lightOrientation*vec4(vertexPosition, 1.0);\n"
"}\0";
const char *fragmentLight=
"#version 400 core\n"
"out vec4 fragmentColor;\n"
"void main() {\n"
"fragmentColor=vec4(1.0, 1.0, 1.0, 1.0);\n"
"}\0";
А вот функция отображения:
void TForm1::display()
{
GLuint loc1, loc2, loc3, loc4, loc5, loc6;
float swap[16];
float normal[16]={0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0};
//first we render a shadow map
{
glUseProgram(shaderT1);
glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer[0]);
glClearColor(20000.0f, 0.0f, 0.0f, 0.0f);
glDepthMask(GL_TRUE);
glDepthRange(0, 1);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glViewport(0, 0, textureDim.x, textureDim.y);
glPatchParameteri(GL_PATCH_VERTICES, 3);
loc1=glGetUniformLocation(shaderT1, "model\0");
loc2=glGetUniformLocation(shaderT1, "lightOrientation\0");
loc3=glGetUniformLocation(shaderT1, "view\0");
swap[0]=1.0; swap[1]=0.0; swap[2]=0.0; swap[3]=0.0;
swap[4]=0.0; swap[5]=1.0; swap[6]=0.0; swap[7]=0.0;
swap[8]=0.0; swap[9]=0.0; swap[10]=1.0; swap[11]=0.0;
swap[12]=-lightMatrix[12]; swap[13]=-lightMatrix[13]; swap[14]=-lightMatrix[14]; swap[15]=1.0;
glUniformMatrix4fv(loc1, 1, GL_FALSE, triangleMatrix);
glUniformMatrix4fv(loc2, 1, GL_FALSE, swap);
glUniformMatrix4fv(loc3, 1, GL_FALSE, view);
glBindVertexArray(VAO[1]);
glDrawArrays(GL_PATCHES, 0, 3);
glUniformMatrix4fv(loc1, 1, GL_FALSE, identity);
glUniformMatrix4fv(loc2, 1, GL_FALSE, swap);
glUniformMatrix4fv(loc3, 1, GL_FALSE, view);
glBindVertexArray(VAO[0]);
glDrawArrays(GL_PATCHES, 0, 6);
}
//then we render the world and make use of that rendered shadow map
{
glUseProgram(shaderT2);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDepthMask(GL_TRUE);
glDepthRange(0, 1);
glClearColor(0.0f, 1.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glUniform1i(glGetUniformLocation(shaderT2, "tex1"), 1);
glActiveTexture(GL_TEXTURE0+1);
glBindTexture(GL_TEXTURE_2D_ARRAY, texID[0]);
glViewport(0, 0, 512, 512);
loc1=glGetUniformLocation(shaderT2, "model\0");
loc2=glGetUniformLocation(shaderT2, "view\0");
loc3=glGetUniformLocation(shaderT2, "normal\0");
loc4=glGetUniformLocation(shaderT2, "colour\0");
loc5=glGetUniformLocation(shaderT2, "projection\0");
loc6=glGetUniformLocation(shaderT2, "lightOrientation\0");
//render a rectangle where the shadow is drawn onto
glUniformMatrix4fv(loc1, 1, GL_FALSE, identity);
glUniformMatrix4fv(loc2, 1, GL_FALSE, view);
matrixMultiply4D(swap, view, identity);
inverseMatrix4D(swap, swap);
transpose4D(normal, swap);
glUniformMatrix4fv(loc3, 1, GL_FALSE, normal);
glUniform4fv(loc4, 1, red);
glUniformMatrix4fv(loc5, 1, GL_FALSE, projection);
swap[0]=1.0; swap[1]=0.0; swap[2]=0.0; swap[3]=0.0;
swap[4]=0.0; swap[5]=1.0; swap[6]=0.0; swap[7]=0.0;
swap[8]=0.0; swap[9]=0.0; swap[10]=1.0; swap[11]=0.0;
swap[12]=-lightMatrix[12]; swap[13]=-lightMatrix[13]; swap[14]=-lightMatrix[14]; swap[15]=1.0;
glUniformMatrix4fv(loc6, 1, GL_FALSE, swap);
glBindVertexArray(VAO[0]);
glDrawArrays(GL_TRIANGLES, 0, 6);
//render the triangle which makes a shadow
glUniformMatrix4fv(loc1, 1, GL_FALSE, triangleMatrix);
glUniformMatrix4fv(loc2, 1, GL_FALSE, view);
matrixMultiply4D(swap, view, triangleMatrix);
inverseMatrix4D(swap, swap);
transpose4D(normal, swap);
glUniformMatrix4fv(loc3, 1, GL_FALSE, normal);
glUniform4fv(loc4, 1, yellow);
glUniformMatrix4fv(loc5, 1, GL_FALSE, projection);
swap[0]=1.0; swap[1]=0.0; swap[2]=0.0; swap[3]=0.0;
swap[4]=0.0; swap[5]=1.0; swap[6]=0.0; swap[7]=0.0;
swap[8]=0.0; swap[9]=0.0; swap[10]=1.0; swap[11]=0.0;
swap[12]=-lightMatrix[12]; swap[13]=-lightMatrix[13]; swap[14]=-lightMatrix[14]; swap[15]=1.0;
glUniformMatrix4fv(loc6, 1, GL_FALSE, swap);
glBindVertexArray(VAO[1]);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
//finally render a white triangle which represents a location of the light
{
glUseProgram(shaderT3);
glBindFramebuffer(GL_FRAMEBUFFER, 0);
glDepthMask(GL_TRUE);
glDepthRange(0, 1);
glViewport(0, 0, 512, 512);
loc1=glGetUniformLocation(shaderT3, "view\0");
loc2=glGetUniformLocation(shaderT3, "projection\0");
loc3=glGetUniformLocation(shaderT3, "lightOrientation\0");
glUniformMatrix4fv(loc1, 1, GL_FALSE, view);
glUniformMatrix4fv(loc2, 1, GL_FALSE, projection);
glUniformMatrix4fv(loc3, 1, GL_FALSE, lightMatrix);
glBindVertexArray(VAO[2]);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
glFinish();
//rotate a light on it's orbit
matrixMultiply4D(lightMatrix, rotationMatrix, lightMatrix);
}
Я взял четыре фильма, представляющие тестовую программу и строки кода 1-4 выше. Ниже фильм 1 сделано с кодом 1:
Movie 2 с кодом 2:
Movie 3 с кодом 3:
Movie 4 с кодом 4:
Вы можете видеть, что фильм 4 является единственным, в котором работает теневое отображение (нет тени в пограничной зоне между двумя полушариями, но я могу жить с этим. Однако, если кто-то знает, как это исправить, я был бы рад, если вы скажете мне). Но он не работает в главном проекте! Я надеюсь, что вы могли бы дать мне совет о том, что может быть не так, что я должен проверить или дать мне ваши рабочие двойные параболоида образцы тени отображения кода ...
У меня была та же проблема, я думаю, я получал линию «шов» на границе между двумя параболоидами. Смотрите: https://stackoverflow.com/questions/44118994/dual-paraboloid-shadow-texture-edge-seams Это то, что вы получаете? –