我使用OpenGL在synthwave样式上创建了一些山脉和网格地板。在后期处理上产生的唯一影响是轻微的花开,但线条出了点问题:
当我进一步看时,线条很快开始画得很差。有时它们不是绘制的,或者只是一块。如果我旋转相机,这些线条的绘制甚至会有所不同。
如果我将相机粘贴在地板上的次数越多,情况就越糟:
我尝试了几件事:禁用我的GC(NVidia)的抗锯齿,将每个滤镜纹理设置为GL_LINEAR而不是GL_NEAREST,深度缓冲区的精度为32位,而不是24位。
怎么了?
这是代码,我试图删除尽可能多的代码
init函数:
void initBase(int argc, char* argv[]) {
YLogConsole::createInstance();
glutInit(&argc, argv);
glutSetOption(
GLUT_ACTION_ON_WINDOW_CLOSE,
GLUT_ACTION_GLUTMAINLOOP_RETURNS
);
glutInitWindowSize(BaseWidth, BaseHeight);
glutInitWindowPosition(0, 0);
glutInitDisplayMode(GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGBA);
YLog::log(YLog::ENGINE_INFO, (toString(argc) + " arguments en ligne de commande.").c_str());
FullScreen = false;
for (int i = 0; i<argc; i++)
{
if (argv[i][0] == 'f')
{
YLog::log(YLog::ENGINE_INFO, "Arg f mode fullscreen.\n");
FullScreen = true;
}
}
MainWindowId = glutCreateWindow("Yocto");
glutReshapeWindow(BaseWidth, BaseHeight);
setFullScreen(FullScreen);
if (MainWindowId < 1)
{
YLog::log(YLog::ENGINE_ERROR, "Erreur creation de la fenetre.");
exit(EXIT_FAILURE);
}
GLenum glewInitResult = glewInit();
if (glewInitResult != GLEW_OK)
{
YLog::log(YLog::ENGINE_ERROR, ("Erreur init glew " + std::string((char*)glewGetErrorString(glewInitResult))).c_str());
exit(EXIT_FAILURE);
}
//Affichage des capacités du système
YLog::log(YLog::ENGINE_INFO, ("OpenGL Version : " + std::string((char*)glGetString(GL_VERSION))).c_str());
glutDisplayFunc(updateBase);
glutReshapeFunc(resizeBase);
glutKeyboardFunc(keyboardDown);
glutKeyboardUpFunc(keyboardUp);
glutSpecialFunc(specialDown);
glutSpecialUpFunc(specialUp);
glutMouseFunc(mouseClick);
glutMotionFunc(mouseMoveActive);
glutPassiveMotionFunc(mouseMovePassive);
glutIgnoreKeyRepeat(1);
//Initialisation du YRenderer
Renderer = YRenderer::getInstance();
Renderer->setRenderObjectFun(renderObjectsBase);
Renderer->setRender2DFun(render2dBase);
Renderer->setBackgroundColor(YColor());
Renderer->initialise(&TimerGPURender);
//On applique la config du YRenderer
glViewport(0, 0, Renderer->ScreenWidth, Renderer->ScreenHeight);
Renderer->resize(Renderer->ScreenWidth, Renderer->ScreenHeight);
//Ecrans de jeu
ScreenManager = new GUIScreenManager();
uint16 x = 10;
uint16 y = 10;
ScreenJeu = new GUIScreen();
ScreenStats = new GUIScreen();
//Bouton pour afficher les params
GUIBouton * btn = new GUIBouton();
btn->Titre = std::string("Params");
btn->X = x;
btn->Y = y;
btn->setOnClick(clickBtnParams);
ScreenJeu->addElement(btn);
y += btn->Height + 5;
btn = new GUIBouton();
btn->Titre = std::string("Stats");
btn->X = x;
btn->Y = y;
btn->setOnClick(clickBtnStats);
ScreenJeu->addElement(btn);
y += btn->Height + 1;
//Ecran de stats
y = btn->Height + 15;
LblFps = new GUILabel();
LblFps->Text = "FPS";
LblFps->X = x;
LblFps->Y = y;
LblFps->Visible = true;
ScreenStats->addElement(LblFps);
//Ecran de parametrage
x = 10;
y = 10;
ScreenParams = new GUIScreen();
GUIBouton * btnClose = new GUIBouton();
btnClose->Titre = std::string("Close");
btnClose->X = x;
btnClose->Y = y;
btnClose->setOnClick(clickBtnClose);
ScreenParams->addElement(btnClose);
ScreenStats->addElement(btnClose);
//Ecran a rendre
ScreenManager->setActiveScreen(ScreenJeu);
//Init YCamera
Renderer->Camera->setPosition(YVec3f(320, 320, 320));
Renderer->Camera->setLookAt(YVec3f(0, 0, 0));
Renderer->Camera->setProjectionPerspective(Instance->Fov,
(float)Instance->Renderer->ScreenWidth / (float)Instance->Renderer->ScreenHeight,
Instance->NearPlane, Instance->FarPlane);
//Init YTimer
Timer = new YTimer();
//Chargement des shaders
Instance->loadShaders();
//Init pour classe fille
init();
//On start le temps
Timer->start();
YLog::log(YLog::ENGINE_INFO, "[ Yocto initialized ]\nPress : \n - f to toggle fullscreen\n - F1 for png screen shot\n - F5 to hot-reload shaders");
}
主循环:
void SynthEngine::renderObjects()
{
Renderer->updateMatricesFromOgl();
glUseProgram(shaderWorld);
Renderer->sendMatricesToShader(shaderWorld);
dec->getGround()->render();
}
UpdateMatriceFromOgl:
void updateMatricesFromOgl() {
float matMvTab[16];
glGetFloatv(GL_MODELVIEW_MATRIX, matMvTab);
memcpy(MatMV.Mat.t, matMvTab, 16 * sizeof(float));
MatMV.transpose();
float matProjTab[16];
glGetFloatv(GL_PROJECTION_MATRIX, matProjTab);
memcpy(MatP.Mat.t, matProjTab, 16 * sizeof(float));
MatP.transpose();
MatMVP = MatP;
MatMVP *= MatMV;
MatV.createViewMatrix(Camera->Position, Camera->LookAt, Camera->UpVec);
MatIV = MatV;
MatIV.invert();
MatM = MatIV;
MatM *= MatMV;
MatIM = MatM;
MatIM.invert();
MatNorm = MatM;
MatNorm.invert();
MatNorm.transpose();
MatIP = MatP;
MatIP.invert();
}
渲染功能(VBO),textureIndex和textureCubeIndex始终为0:
void YVbo::render(GBuffer * inBuffer) {
//La stat globales
YRenderer::NbVBOFacesRendered += NbVertices / 3;
if (textureIndex)
{
glBindTexture(GL_TEXTURE_2D, textureIndex);
}
if (textureCubeIndex)
{
glBindTexture(GL_TEXTURE_CUBE_MAP, textureCubeIndex);
}
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
for (int i = 0; i<NbElements; i++)
glEnableVertexAttribArray(i);
if (StorageMethod == PACK_BY_ELEMENT_TYPE) {
for (int i = 0; i<NbElements; i++)
glVertexAttribPointer(i, Elements[i].NbFloats, GL_FLOAT, GL_FALSE, 0, (void*)(Elements[i].OffsetFloats * sizeof(float)));
} else {
for (int i = 0; i<NbElements; i++)
glVertexAttribPointer(i, Elements[i].NbFloats, GL_FLOAT, GL_FALSE, TotalNbFloatForOneVertice * sizeof(float), (void*)(Elements[i].OffsetFloats * sizeof(float)));
}
YEngine::Instance->TimerGPURender.startAccumPeriod();
glDrawArrays(GL_TRIANGLES, 0, NbVertices);
YEngine::Instance->TimerGPURender.endAccumPeriod();
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_CUBE_MAP, 0);
}
ShaderWorld的顶点着色器:
#version 400
uniform mat4 mvp;
uniform float elapsed;
layout(location = 0) in vec3 position_in;
layout(location = 1) in vec4 color_border_in;
layout(location = 2) in vec4 color_fill_in;
out VertexAttrib
{
vec4 colorFill;
vec4 colorBorder;
} vertex;
void main()
{
gl_Position = mvp * vec4(position_in, 1);
vertex.colorBorder = color_border_in;
vertex.colorFill = color_fill_in;
}
几何着色器
#version 400
out vec4 color_border;
out vec4 color_fill;
out vec3 bary;
in VertexAttrib
{
vec4 colorFill;
vec4 colorBorder;
} vertex[];
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
void main()
{
for (int i = 0; i < 3; i++)
{
color_border = vertex[i].colorBorder;
color_fill = vertex[i].colorFill;
gl_Position = gl_in[i].gl_Position;
if (i == 0)
bary = vec3(0, 0, 1);
if (i == 1)
bary = vec3(0, 1, 0);
if (i == 2)
bary = vec3(1, 0, 0);
EmitVertex();
}
EndPrimitive();
}
片段着色器:
#version 400
in vec4 color_border;
in vec4 color_fill;
in vec3 bary;
layout (location = 0) out vec4 color;
layout (location = 1) out vec4 passColor;
float toleranceLight = 0.7;
void main()
{
vec4 interColor;
if ((bary.x) < 0.01 || (bary.y) < 0.01 || ((bary.z) < 0.01 && color_border.r == 0))
{
interColor = color_border;
}
else
{
interColor = color_fill;
}
if (max(interColor.r,max(interColor.g, interColor.b)) > toleranceLight)
{
passColor = interColor;
}
else
{
passColor = vec4(0,0,0,1);
}
color = interColor;
}
答案 0 :(得分:0)
这里的主要问题是vec3 bary的透视插值及其布尔性质,导致在color_border和color_fill边缘周围出现伪像。考虑基于重插值的边缘和填充颜色之间的某种插值。
或者,您可以考虑映射表示边缘与填充的蒙版纹理。您需要确保生成mipmap,并在运行时将其与各向异性过滤器一起使用。
另外,在这种情况下,您根本不需要几何着色器。只需直接从顶点着色器使用gl_VertexID%3并从那里输出bary。