#c #winapi #opengl #rendering #pixelformat
Вопрос:
Я не могу понять, почему треугольник, отображаемый в приведенном ниже примере, имеет черный цвет (автоматическая интерполяция не работает)
INT WINAPI
WinMain(
HINSTANCE, HINSTANCE, LPSTR, int
)
{
HINSTANCE hInstance = GetModuleHandle(0);
GLOBAL_INFO("Application started");
WNDCLASSA window_class{};
window_class.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
window_class.lpfnWndProc = WndProc;
window_class.hInstance = hInstance;
window_class.lpszClassName = "M9Main";
if (!RegisterClassA(amp;window_class))
{
return 0;
}
HWND window_handle = CreateWindow(
"M9Main",
"m9",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
R_WIDTH, R_HEIGHT,
NULL, NULL,
hInstance,
NULL
);
if (!window_handle)
{
return 0;
}
if (!win32_opengl_init(window_handle))
{
return 0;
}
ShowWindow(window_handle, SW_SHOWDEFAULT);
global_running = M9_TRUE;
const char* vs =
#include "shaders/sample.vs.glsl"
const char* fs =
#include "shaders/sample.fs.glsl"
u32 shader = opengl_load_shaders(vs, fs);
r32 vertices[] {
0.5f, -0.5f, 1.0f, 0.0f, 0.0f,
-0.5f, -0.5f, 0.0f, 1.0f, 0.0f,
-0.5f, 0.5f, 0.0f, 0.0f, 1.0f,
};
u32 VBO{};
u32 VAO{};
glGenVertexArrays(1, amp;VAO);
glGenBuffers(1, amp;VBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_DYNAMIC_DRAW);
glVertexAttribPointer(
0, 2,
GL_FLOAT, GL_FALSE,
5 * sizeof(r32), (void*)0
);
glEnableVertexAttribArray(0);
glVertexAttribPointer(
1, 3,
GL_FLOAT, GL_FALSE,
5 * sizeof(r32), (void*)(sizeof(r32) * 2)
);
glEnableVertexAttribArray(1);
glUseProgram(shader);
i32 uDisp = glGetUniformLocation(shader, "uDisp");
r32 disp[2]{};
r32 delta = 0.001f;
const game_controller_stateamp; ctl = global_game_input.keyboard_state;
while (global_running)
{
process_messages(global_game_input);
glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
if (ctl.move_up.pressed)
{
disp[1] = delta;
}
else if (ctl.move_down.pressed)
{
disp[1] -= delta;
}
else if (ctl.move_left.pressed)
{
disp[0] -= delta;
}
else if (ctl.move_right.pressed)
{
disp[0] = delta;
}
glUniform2f(uDisp, disp[0], disp[1]);
glBindVertexArray(VAO);
glDrawArrays(GL_TRIANGLES, 0, 3);
SwapBuffers(opengl_context.device_ctx);
}
return 0;
}
Мои шейдеры:
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
uniform vec2 uDisp;
out vec3 Color;
void main()
{
gl_Position = vec4(aPos.x uDisp.x, aPos.y uDisp.y, 0.0f, 1.0);
Color = aColor;
};
#version 330 core
out vec4 outcolor;
in vec3 inColor;
void main()
{
outcolor = vec4(inColor, 1.0f);
};
Я загружаю OpenGL вручную (без GLAD или smth), также я не использую библиотеку, такую как GLFW, для управления окном. Поэтому я должен инициализировать контекст OpenGL и описать формат пикселей. Все это делается в win32_opengl_init
функциональном режиме:
static b32
win32_opengl_init(HWND hwnd)
{
opengl_context.device_ctx = GetDC(hwnd);
HDCamp; dc = opengl_context.device_ctx;
PIXELFORMATDESCRIPTOR pfd{};
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 32;
pfd.cDepthBits = 24;
pfd.cStencilBits = 8;
pfd.iLayerType = PFD_MAIN_PLANE;
// TODO: display error message using last error code
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, amp;pfd), amp;pfd))
{
GLOBAL_ERROR("Cannot set pixel format: %lu", GetLastError());
return M9_FALSE;
}
HGLRC rendering_context = wglCreateContext(dc);
if (!rendering_context)
{
GLOBAL_ERROR("Cannot create rendering context: %lu", GetLastError());
return M9_FALSE;
}
opengl_context.rendering_ctx = rendering_context;
if (!win32_opengl_make_ctx_current(opengl_context))
{
GLOBAL_ERROR("Cannot make rendering context current: %lu", GetLastError());
return M9_FALSE;
}
/* loading functions */
GLOBAL_INFO("OpenGL initialized successfully");
return M9_TRUE;
}
Проблема, вероятно, в моем описании формата пикселей, потому что я не вижу никаких других различий между тем, что я делаю, и тем, что происходит в соответствующем учебнике: https://learnopengl.com/Getting-started/Hello-Triangle
Эта проблема исчезнет, когда я начну использовать GLFW для создания контекста opengl … Но я хочу все делать своими руками, без каких-либо библиотек.
Ответ №1:
Я не могу понять, почему треугольник, отображаемый в приведенном ниже примере, имеет черный цвет (автоматическая интерполяция не работает)
Но это довольно легко увидеть:
Ваш Вершинный шейдер:
out vec3 Color;
Ваш Шейдер Фрагментов:
in vec3 inColor;
Они не совпадают, поэтому inColor
просто не определены в вашем шейдере фрагментов.
Эта проблема исчезает, когда я начинаю использовать GLFW для создания контекста opengl …
Я действительно не понимаю, как использование GLFW не столкнется с проблемой, описанной выше. Кстати, когда вы создаете свой контекст, я рекомендую вам явно создать контекст основного профиля, и если вы хотите сделать это вручную wgl
, для этого потребуется много стандартного кода.
Комментарии:
1. О, мой бог… Это была такая глупая ошибка. Я действительно не знал, что имена ввода и вывода должны быть одинаковыми как в вершинных, так и в фрагментных шейдерах. Спасибо! С GLFW я использовал другие шейдеры, соответствующие друг другу. Спасибо за совет!