nvidia opengl framebuffer заставляет vsync включить
По сути, я реализовал гамма-коррекцию в игре на основе q3, чтобы избавиться от надоедливого SetDeviceGammaRamp.
Я использую GL_EXT_framebuffer_object для вершинного шейдера после процесса. Он работает довольно хорошо, за исключением того, что он имеет странное поведение на nvidia gpus: он заставляет vsync быть включенным, за исключением случаев, когда он явно отключен на панели управления. Если я использую настройки стандартной панели управления и кадровый буфер включен, vsync принудительно запускается, но если я удаляю кадровый буфер, он возвращается к нормальному поведению.
- wglSwapIntervalEXT ничего не делает
- Я тестировал его на мобильном GPU NVIDIA, кто-то мог воспроизвести его на настольном GPU
- Я также протестировал интегрированный Intel GPU и два разных AMD GPU, и у всех них не было проблемы.
инициализация: (неважно, я думаю)
// ouned: gamma correction
const char *g_GammaVertexShaderARB = {
"void main(void)" "\n"
"{" "\n"
"gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;" "\n"
"gl_TexCoord[0] = gl_MultiTexCoord0;" "\n"
"}"
};
const char *g_GammaFragmentShaderARB = {
"uniform sampler2D sceneBuffer;" "\n"
"uniform float gamma;" "\n"
"\n"
"void main(void)" "\n"
"{" "\n"
"vec2 uv = gl_TexCoord[0].xy;" "\n"
"vec3 color = texture2D(sceneBuffer, uv).rgb;" "\n"
"if (uv.x<0.50)" "\n"
"gl_FragColor.rgb = pow(color, vec3(1.0 / 1.5));" "\n"
"else" "\n"
"gl_FragColor.rgb = color;" "\n"
"gl_FragColor.a = 1.0;" "\n"
"}"
};
tr.m_hVShader = qglCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
qglShaderSourceARB(tr.m_hVShader, 1, (const GLcharARB **)&g_GammaVertexShaderARB, NULL);
qglCompileShaderARB(tr.m_hVShader);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed compiling gamma vertrex shader\n");
}
tr.m_hFShader = qglCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);
qglShaderSourceARB(tr.m_hFShader, 1, (const GLcharARB **)&g_GammaFragmentShaderARB, NULL);
qglCompileShaderARB(tr.m_hFShader);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed compiling gamma fragment shader\n");
}
tr.gammaProgram = qglCreateProgramObjectARB();
qglAttachObjectARB(tr.gammaProgram, tr.m_hVShader);
qglAttachObjectARB(tr.gammaProgram, tr.m_hFShader);
qglLinkProgramARB(tr.gammaProgram);
if (qglGetError() != GL_NO_ERROR) {
ri.Printf(PRINT_ERROR, "Failed linking shaders\n");
}
qglUseProgramObjectARB(tr.gammaProgram);
tr.gammaUniformLoc = qglGetUniformLocationARB(tr.gammaProgram, "gamma");
tr.gammaSceneBufferLoc = qglGetUniformLocationARB(tr.gammaProgram, "sceneBuffer");
qglValidateProgramARB(tr.gammaProgram);
qglUseProgramObjectARB(0);
// framebuffer object
tr.gammaFramebuffer = 0;
qglGenFramebuffersEXT(1, &tr.gammaFramebuffer);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tr.gammaFramebuffer);
// depth buffer
tr.gammaRenderDepthBuffer = 0;
qglGenRenderbuffersEXT(1, &tr.gammaRenderDepthBuffer);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, glConfig.vidWidth, glConfig.vidHeight);
tr.gammaRenderTarget = 0;
qglGenTextures(1, &tr.gammaRenderTarget);
qglBindTexture(GL_TEXTURE_2D, tr.gammaRenderTarget);
qglTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, glConfig.vidWidth, glConfig.vidHeight, 0, GL_RGB, GL_UNSIGNED_BYTE, 0);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
qglTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
qglGenerateMipmapEXT(GL_TEXTURE_2D);
qglBindTexture(GL_TEXTURE_2D, 0);
qglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, tr.gammaRenderTarget, 0);
qglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
В начале кадра:
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, tr.gammaFramebuffer);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, tr.gammaRenderDepthBuffer);
qglDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
на конце кадра:
qglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
qglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0);
if (!backEnd.projection2D) {
qglViewport(0, 0, glConfig.vidWidth, glConfig.vidHeight);
qglScissor(0, 0, glConfig.vidWidth, glConfig.vidHeight);
qglMatrixMode(GL_PROJECTION);
qglLoadIdentity();
qglOrtho(0, glConfig.vidWidth, glConfig.vidHeight, 0, 0, 1);
qglMatrixMode(GL_MODELVIEW);
qglLoadIdentity();
GL_State(GLS_DEPTHTEST_DISABLE);
}
qglUseProgramObjectARB(tr.gammaProgram);
qglEnable(GL_TEXTURE_2D);
qglUniform1iARB(tr.gammaSceneBufferLoc, 0);
qglColor3f(tr.identityLight, tr.identityLight, tr.identityLight);
qglActiveTextureARB(GL_TEXTURE0);
qglBindTexture(GL_TEXTURE_2D, tr.gammaRenderTarget);
qglBegin(GL_QUADS);
qglTexCoord2f(0, 1);
qglVertex2f(0, 0);
qglTexCoord2f(1, 1);
qglVertex2f(glConfig.vidWidth, 0);
qglTexCoord2f(1, 0);
qglVertex2f(glConfig.vidWidth, glConfig.vidHeight);
qglTexCoord2f(0, 0);
qglVertex2f(0, glConfig.vidHeight);
qglEnd();
qglUseProgramObjectARB(0);
Итак, что еще может привести к включению vsync?