Форум программистов, компьютерный форум, киберфорум
OpenGL
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.65/104: Рейтинг темы: голосов - 104, средняя оценка - 4.65
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771

Обводка объекта с использованием шейдера

01.10.2021, 19:34. Показов 23320. Ответов 180
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Есть игра, в которой я могу определить, когда начинает / заканчивает рисоваться нужный мне объект и "внедриться" в нужный момент. Я хочу сделать так, чтобы контур нужного мне объекта обводился. Подобие того что я хочу Вы можете увидеть на прикреплённом изображении.

1. Возможно ли сделать обводку объекта без повторной его отрисовки? (я не знаю как игра рисует объекты, да и это будет сказываться на производительности)
2. Возможно ли сделать это без шейдера и повторной отрисовки? (один человек говорил мне что без шейдера нужно будет рисовать дважды)
3. Как это сделать? (я не прошу написать за меня весь код, однако я очень мало понимаю в шейдерах. У меня есть две "точки" - начало рисования и конец, как и что нужно написать в самом начале чтобы увидеть хоть какие-то изменения и далее уже самому потыкать)
Миниатюры
Обводка объекта с использованием шейдера  
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
01.10.2021, 19:34
Ответы с готовыми решениями:

Обводка объекта
Возможно ли нарисовать обводку объекта, при условиях, что нельзя использовать шейдеры и сам объект рисую не я? У меня есть возможность...

Обводка объекта точками в OpenCV
Здравствуйте,только открыл для себя OpenCV.Задача такова:будут объекты на белом фоне,хочу обвести объект максимальным количеством точек...

написать программу движущийся графический объект с двумя способоми с использованием статического объекта и с использованием динамического объекта
Движение закрашенного прямоугольника по треугольному контуру с изменением цвета при изменении направления движения.

180
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
29.11.2022, 14:39
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
У меня не получается корректно его перенести в проект
"Не получается" - это не описание проблемы.
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
можешь, пожалуйста, скинуть полный готовый файл?
Готовый файл чего? Чего тебе не хватает в этом примере?
0
9987 / 2959 / 497
Регистрация: 05.10.2013
Сообщений: 8,102
Записей в блоге: 243
29.11.2022, 15:36
Цитата Сообщение от Dimas_Pomor Посмотреть сообщение
Post-processing
Конкретно это видео автор мог не видеть, а я не увидел, что он выше вашего сообщения ответил. Извините за мою невнимательность.
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
30.11.2022, 22:35  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
"Не получается" - это не описание проблемы.
Я не понимаю в чём моя ошибка. Готовый файл, который я мог бы собрать и сам потыкать, помог бы мне разобраться в этой проблеме.

Вот мой текущий код
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
const char* fragmentSource = R"(
    #version 460
 
    uniform vec2 uDelta;
    uniform vec2 uDirection;
    uniform sampler2D uTexture;
 
    void main()
    {
        vec2 uv = gl_TexCoord[0].st;
        float color = texture2D(uTexture, uv).r;
        vec2 off1 = uDirection * 1.5;
        vec2 off2 = uDirection * 3.0;
 
        color += texture2D(uTexture, uv + uDelta * off1).r * 0.5 +
                    texture2D(uTexture, uv - uDelta * off1).r * 0.5 +
                    texture2D(uTexture, uv + uDelta * off2).r * 0.25 +
                    texture2D(uTexture, uv - uDelta * off2).r * 0.25;
 
        gl_FragColor = vec4(1.0f);
    }
)";
 
constexpr int fboSizeX = 800;
constexpr int fboSizeY = 600;
 
unsigned int tex[2] = {};
unsigned int fbo = 0;
 
void drawRectangle()
{
    glPushMatrix();
    glLoadIdentity();
    glMatrixMode(GL_PROJECTION);
    glPushMatrix();
    glLoadIdentity();
    glMatrixMode(GL_TEXTURE);
    glPushMatrix();
    glLoadIdentity();
 
    glBegin(GL_QUADS);
    glTexCoord2d(0.0, 0.0);
    glVertex2d(-1.0, -1.0);
    glTexCoord2d(1.0, 0.0);
    glVertex2d(1.0, -1.0);
    glTexCoord2d(1.0, 1.0);
    glVertex2d(1.0, 1.0);
    glTexCoord2d(0.0, 1.0);
    glVertex2d(-1.0, 1.0);
    glEnd();
 
    glPopMatrix();
    glMatrixMode(GL_PROJECTION);
    glPopMatrix();
    glMatrixMode(GL_MODELVIEW);
    glPopMatrix();
}
 
bool initialize()
{
    glGenTextures(2, tex);
 
    for (auto texture : tex)
    {
        glBindTexture(GL_TEXTURE_2D, texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
 
        glTexImage2D(GL_TEXTURE_2D,
            0,
            GL_RGBA,
            fboSizeX,
            fboSizeY,
            0,
            GL_RGBA,
            GL_UNSIGNED_BYTE,
            nullptr);
    }
 
    glBindTexture(GL_TEXTURE_2D, 0);
 
    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    return true;
}
 
int WINAPI mySwapBuffers(HDC pDeviceContextHandle)
{
    /* Getting OpenGL function pointers */
    const static int version = gladLoaderLoadGL();
 
    if (!version)
        return fpSwapBuffers(pDeviceContextHandle);
 
    const static bool init = initialize();
 
    const static unsigned int shader = createShader();
 
    const static int uDirection = glGetUniformLocation(shader, "uDirection");
    const static int uDelta = glGetUniformLocation(shader, "uDelta");
 
    // теперь делаем обводку
    // делать это нужно один раз в конце рисования сцены
 
    // блюрим силуэты (блюр в два прохода)
    glEnable(GL_TEXTURE_2D);
 
    glUseProgram(shader);
    glUniform2fv(uDelta, 1, value_ptr(glm::vec2{ 1.0f / fboSizeX, 1.0f / fboSizeY }));
 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    glViewport(0, 0, fboSizeX, fboSizeY);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[1], 0);
    glBindTexture(GL_TEXTURE_2D, tex[0]);
 
    glUniform2fv(uDirection, 1, value_ptr(glm::vec2{ 1.0f, 0.0f }));
    drawRectangle(); // glCallList(2);
 
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
    glBindTexture(GL_TEXTURE_2D, tex[1]);
 
    glUniform2fv(uDirection, 1, value_ptr(glm::vec2{ 0.0f, 1.0f }));
    drawRectangle(); // glCallList(2);
 
    glUseProgram(0);
    // заливаем цветом экран там,
    // где в буфере трафарета не выставлен младший бит
    // и есть размытые силуэты объектов
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, fboSizeX, fboSizeY);
    glBindTexture(GL_TEXTURE_2D, tex[0]);
    glEnable(GL_BLEND);
    glBlendEquation(GL_FUNC_ADD);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_STENCIL_TEST);
    glDisable(GL_DEPTH_TEST);
    glStencilFunc(GL_NOTEQUAL, 0x01, 0xff);
    glStencilMask(0x00);
    glColor3d(1.0, 1.0, 1.0);
    drawRectangle(); // glCallList(2);
    glStencilMask(0xff);
    glDisable(GL_STENCIL_TEST);
    glDisable(GL_BLEND);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_TEXTURE_2D);
 
    glClear(GL_STENCIL_BUFFER_BIT);
    return fpSwapBuffers(pDeviceContextHandle);
}
 
void WINAPI myglCallList(GLuint list)
{
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_ALWAYS, 0x01, 0xff);
    glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
    fpglCallList(list);
    glDisable(GL_STENCIL_TEST);
 
    glBindFramebuffer(GL_FRAMEBUFFER, fbo);
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
    glViewport(0, 0, fboSizeX, fboSizeY);
    glEnable(GL_COLOR_LOGIC_OP);
    glLogicOp(GL_SET);
    fpglCallList(list);
    glDisable(GL_COLOR_LOGIC_OP);
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, fboSizeX, fboSizeY);
}


Вот что я получаю (вдалеке это житель который рисовался при помощи glCallList)
Миниатюры
Обводка объекта с использованием шейдера  
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
30.11.2022, 22:40  [ТС]
Если перед рисованием прямоугольника добавить glColor3d(1.0, 1.0, 1.0); то вся область игры становится белой. Вообще ничего там не выделяется.
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
30.11.2022, 22:41

Не по теме:

Цитата Сообщение от eXpl01TeR Посмотреть сообщение
я мог бы собрать и сам потыкать
Ох уж это программирование методом тыка...


Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Вот мой текущий код
Но он ничего не рисует...
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Вот что я получаю
И какое это имеет отношение к коду?


Вопрос, ты можешь отрисовать все объекты, которые нужно обвести в хуке SwapBuffers?
Или только в других местах?
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
30.11.2022, 22:49  [ТС]
Инициализация и создание шейдера происходит без ошибок (glGetError ничего не возвращает)

Добавлено через 1 минуту
Цитата Сообщение от zayats80888 Посмотреть сообщение
Но он ничего не рисует...
Как это? Он же вызывает рисование прямоугольника который с текстурой.

Цитата Сообщение от zayats80888 Посмотреть сообщение
Вопрос, ты можешь отрисовать все объекты, которые нужно обвести в хуке SwapBuffers?
Я могу рисовать что угодно в хуке, но какие рисовались объекты и как я не знаю. По этому я и хотел сделать через запись в текстуру чтоб потом в конце как-то обвести объекты внутри и отрисовать ее на весь кадр.
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
30.11.2022, 22:59
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Как это?
Пять минунт назад код заканчивался на 89 строке. Либо непрогуз, либы ты отредактировал.
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Я могу рисовать что угодно в хуке, но какие рисовались объекты и как я не знаю.
А как ты сундуки обводил до этого?
Сейчас я вижу, что у тебя просто перехват glCallList, т.е. ты рисуешь вообще ВСЁ! А еще не очищаешь буфер цвета(текстуру).
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
30.11.2022, 23:03  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
Пять минунт назад код заканчивался на 89 строке. Либо непрогуз, либы ты отредактировал.
Думал никто не успеет заметить :c

Цитата Сообщение от zayats80888 Посмотреть сообщение
А как ты сундуки обводил до этого?
Где кубический ESP, я сохранял матрицы и потом при вызове wglSwapBuffers рисовал кубы.
Где кривой ESP с недо-обводкой, там хук glCallList, буфер трафарета но без фреймбуфера и текстуры.

Цитата Сообщение от zayats80888 Посмотреть сообщение
Сейчас я вижу, что у тебя просто перехват glCallList, т.е. ты рисуешь вообще ВСЁ! А еще не очищаешь буфер цвета(текстуру).
В майнкрафт с помощью glCallList рисуются только сущности и сундуки. Остальное при помощи glDrawArrays.
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
30.11.2022, 23:09
Ладно, ща набросаю (это не быстро)...
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
30.11.2022, 23:12  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
Ладно, ща набросаю (это не быстро)...
Спасибо большое
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
30.11.2022, 23:40
Лучший ответ Сообщение было отмечено eXpl01TeR как решение

Решение

eXpl01TeR, вот тебе класс для теста. Там без удаления ресурсов и проверок ошибок почти нет.
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
class test
{
    GLint m_width = 1;
    GLint m_height = 1;
    GLfloat m_quality = 1;
    GLint m_fbo_width = 1;
    GLint m_fbo_height = 1;
 
    GLuint m_textures[2] = {};
    GLuint m_stencil = 0;
    GLuint m_fbo = 0;
    GLuint m_shader = 0;
 
    GLint m_delta_location = -1;
    GLint m_direction_location = -1;
    GLint m_texture_location = -1;
 
    struct state_cache
    {
        GLint texturing = GL_FALSE;
        GLint texture_unit = GL_TEXTURE0;
        GLint texture = 0;
        GLint renderbuffer = 0;
        GLint program = 0;
        GLint fbo = 0;
        GLint blend = GL_FALSE;
        GLint blend_equation_rgb = GL_FUNC_ADD;
        GLint blend_equation_alpha = GL_FUNC_ADD;
        GLint blend_src_rgb = GL_ONE;
        GLint blend_src_alpha = GL_ONE;
        GLint blend_dst_rgb = GL_ZERO;
        GLint blend_dst_alpha = GL_ZERO;
        GLint color_logic_op = GL_FALSE;
        GLint logic_op = GL_COPY;
        GLint viewport[4] = {};
        GLfloat clear_color[4] = {};
        GLint depth = GL_FALSE;
        GLint stencil = GL_FALSE;
        GLint stencil_clear_value = 0;
        GLint stencil_fail = GL_KEEP;
        GLint stencil_pass_depth_fail = GL_KEEP;
        GLint stencil_pass_depth_pass = GL_KEEP;
        GLint stencil_func = GL_ALWAYS;
        GLint stencil_ref = 0;
        GLint stencil_value_mask = -1;
        GLint stencil_writemask = -1;
 
    } m_state_cache;
 
    void save_texture_state()
    {
        m_state_cache.texturing = glIsEnabled(GL_TEXTURE_2D);
        glGetIntegerv(GL_ACTIVE_TEXTURE, &m_state_cache.texture_unit);
        glActiveTexture(GL_TEXTURE0);
        glGetIntegerv(GL_TEXTURE_BINDING_2D, &m_state_cache.texture);
        
    }
 
    void restore_texture_state()
    {
        if (m_state_cache.texturing)
            glEnable(GL_TEXTURE_2D);
        else
            glDisable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, m_state_cache.texture);
        glActiveTexture(m_state_cache.texture_unit);
    }
 
    void save_renderbuffer_state()
    {
        glGetIntegerv(GL_RENDERBUFFER_BINDING, &m_state_cache.renderbuffer);
    }
 
    void restore_renderbuffer_state()
    {
        glBindRenderbuffer(GL_RENDERBUFFER, m_state_cache.renderbuffer);
    }
 
    void save_shader_state()
    {
        glGetIntegerv(GL_CURRENT_PROGRAM, &m_state_cache.program);
    }
 
    void restore_shader_state()
    {
        glUseProgram(m_state_cache.program);
    }
 
    void save_framebuffer_state()
    {
        glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &m_state_cache.fbo);
    }
 
    void restore_framebuffer_state()
    {
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_state_cache.fbo);
    }
 
    void save_blend_state()
    {
        m_state_cache.blend = glIsEnabled(GL_BLEND);
        glGetIntegerv(GL_BLEND_EQUATION_RGB, &m_state_cache.blend_equation_rgb);
        glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &m_state_cache.blend_equation_alpha);
        glGetIntegerv(GL_BLEND_SRC_RGB, &m_state_cache.blend_src_rgb);
        glGetIntegerv(GL_BLEND_SRC_ALPHA, &m_state_cache.blend_src_alpha);
        glGetIntegerv(GL_BLEND_DST_RGB, &m_state_cache.blend_dst_rgb);
        glGetIntegerv(GL_BLEND_DST_ALPHA, &m_state_cache.blend_dst_alpha);
    }
 
    void restore_blend_state()
    {
        if (m_state_cache.blend)
            glEnable(GL_BLEND);
        else
            glDisable(GL_BLEND);
        glBlendEquationSeparate(m_state_cache.blend_equation_rgb, m_state_cache.blend_equation_alpha);
        glBlendFuncSeparate(m_state_cache.blend_src_rgb,
                            m_state_cache.blend_dst_rgb,
                            m_state_cache.blend_src_alpha,
                            m_state_cache.blend_dst_alpha);
    }
 
    void save_logic_op_state()
    {
        m_state_cache.color_logic_op = glIsEnabled(GL_COLOR_LOGIC_OP);
        glGetIntegerv(GL_LOGIC_OP_MODE, &m_state_cache.logic_op);
    }
 
    void restore_logic_op_state()
    {
        if (m_state_cache.color_logic_op)
            glEnable(GL_COLOR_LOGIC_OP);
        else
            glDisable(GL_COLOR_LOGIC_OP);
        glLogicOp(m_state_cache.logic_op);
    }
 
    void save_viewport_state()
    {
        glGetIntegerv(GL_VIEWPORT, m_state_cache.viewport);
    }
 
    void restore_viewport_state()
    {
        glViewport(m_state_cache.viewport[0],
                   m_state_cache.viewport[1],
                   m_state_cache.viewport[2],
                   m_state_cache.viewport[3]);
    }
 
    void save_clear_color_state()
    {
        glGetFloatv(GL_COLOR_CLEAR_VALUE, m_state_cache.clear_color);
    }
 
    void restore_clear_color_state()
    {
        glClearColor(m_state_cache.clear_color[0],
                     m_state_cache.clear_color[1],
                     m_state_cache.clear_color[2],
                     m_state_cache.clear_color[3]);
    }
 
    void save_depth_stencil_state()
    {
        m_state_cache.depth = glIsEnabled(GL_DEPTH_TEST);
        m_state_cache.stencil = glIsEnabled(GL_STENCIL_TEST);
        glGetIntegerv(GL_STENCIL_CLEAR_VALUE, &m_state_cache.stencil_clear_value);
        glGetIntegerv(GL_STENCIL_FAIL, &m_state_cache.stencil_fail);
        glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &m_state_cache.stencil_pass_depth_fail);
        glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &m_state_cache.stencil_pass_depth_pass);
        glGetIntegerv(GL_STENCIL_FUNC, &m_state_cache.stencil_func);
        glGetIntegerv(GL_STENCIL_REF, &m_state_cache.stencil_ref);
        glGetIntegerv(GL_STENCIL_VALUE_MASK, &m_state_cache.stencil_value_mask);
        glGetIntegerv(GL_STENCIL_WRITEMASK, &m_state_cache.stencil_writemask);
    }
 
    void restore_depth_stencil_state()
    {
        if (m_state_cache.depth)
            glEnable(GL_DEPTH_TEST);
        else
            glDisable(GL_DEPTH_TEST);
 
        if (m_state_cache.stencil)
            glEnable(GL_STENCIL_TEST);
        else
            glDisable(GL_STENCIL_TEST);
 
        glClearStencil(m_state_cache.stencil_clear_value);
        glStencilOp(m_state_cache.stencil_fail,
                    m_state_cache.stencil_pass_depth_fail,
                    m_state_cache.stencil_pass_depth_pass);
        glStencilFunc(m_state_cache.stencil_func,
                      m_state_cache.stencil_ref,
                      m_state_cache.stencil_value_mask);
        glStencilMask(m_state_cache.stencil_writemask);
    }
 
    void create_shader()
    {
        GLuint shader = glCreateShader(GL_FRAGMENT_SHADER);
 
        const GLchar *data = R"(
      uniform vec2 uDelta;
      uniform vec2 uDirection;
      uniform sampler2D uTexture;
      void main() {
        vec2 uv = gl_TexCoord[0].st;
        float color = texture2D(uTexture, uv).a;
        vec2 off1 = uDirection * 1.5;
        vec2 off2 = uDirection * 3.0;
        color += texture2D(uTexture, uv + uDelta * off1).a * 0.5 +
                 texture2D(uTexture, uv - uDelta * off1).a * 0.5 +
                 texture2D(uTexture, uv + uDelta * off2).a * 0.25 +
                 texture2D(uTexture, uv - uDelta * off2).a * 0.25;
        gl_FragColor = vec4(gl_Color.rgb, color);
      }
        )";
        glShaderSource(shader, 1, &data, nullptr);
        glCompileShader(shader);
 
        GLint status = GL_FALSE;
        glGetShaderiv(shader, GL_COMPILE_STATUS, &status);
        if (status == GL_FALSE)
        {
            std::string buf;
            GLint bufSize = 0;
            glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &bufSize);
            if (bufSize > 1)
            {
                buf.resize(bufSize);
                GLsizei length = 0;
                glGetShaderInfoLog(shader, bufSize, &length, &buf[0]);
                buf.resize(length);
            }
            std::cerr << "shader compile error:\n" << buf << std::endl;
            glDeleteShader(shader);
            return;
        }
 
        GLuint program = glCreateProgram();
        glAttachShader(program, shader);
        glLinkProgram(program);
 
        status = GL_FALSE;
        glGetProgramiv(program, GL_LINK_STATUS, &status);
        if (status == GL_FALSE)
        {
            std::string buf;
            GLint bufSize = 0;
            glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufSize);
            if (bufSize > 1)
            {
                buf.resize(bufSize);
                GLsizei length = 0;
                glGetProgramInfoLog(program, bufSize, &length, &buf[0]);
                buf.resize(length);
            }
            std::cerr << "shader link error:\n" << buf << std::endl;
            glDeleteShader(shader);
            glDeleteProgram(program);
            return;
        }
 
        m_delta_location = glGetUniformLocation(program, "uDelta");
        m_direction_location = glGetUniformLocation(program, "uDirection");
        m_texture_location = glGetUniformLocation(program, "uTexture");
 
        glDetachShader(program, shader);
        glDeleteShader(shader);
 
        m_shader = program;
    }
 
    void create_textures()
    {
        save_texture_state();
        save_renderbuffer_state();
 
        glGenTextures(2, m_textures);
        for (auto texture : m_textures)
        {
            glBindTexture(GL_TEXTURE_2D, texture);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
            
            glTexImage2D(GL_TEXTURE_2D,
                         0,
                         GL_RGBA,
                         m_fbo_width,
                         m_fbo_height,
                         0,
                         GL_RGBA,
                         GL_UNSIGNED_BYTE,
                         nullptr);
        }
 
        glGenRenderbuffers(1, &m_stencil);
        glBindRenderbuffer(GL_RENDERBUFFER, m_stencil);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, m_fbo_width, m_fbo_height);
 
        restore_texture_state();
        restore_renderbuffer_state();
    }
 
    void create_fbo()
    {
        save_framebuffer_state();
 
        GLuint fbo = 0;
        glGenFramebuffers(1, &fbo);
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fbo);
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[0], 0);
        glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_stencil);
        if (glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
        {
            std::cerr << "incomplete fbo\n";
            glDeleteFramebuffers(1, &fbo);
            restore_framebuffer_state();
            return;
        }
        m_fbo = fbo;
 
        save_depth_stencil_state();
        save_clear_color_state();
 
        glStencilMask(0xff);
        glClearStencil(0);
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
        restore_depth_stencil_state();
        restore_clear_color_state();
        restore_framebuffer_state();
    }
 
    void draw_quad(float r = 1, float g = 1, float b = 1)
    {
        glMatrixMode(GL_MODELVIEW);
        glPushMatrix();
        glLoadIdentity();
        glMatrixMode(GL_PROJECTION);
        glPushMatrix();
        glLoadIdentity();
        glMatrixMode(GL_TEXTURE);
        glPushMatrix();
        glLoadIdentity();
 
        glColor3f(r, g, b);
        glBegin(GL_QUADS);
        glTexCoord2f(0, 0);
        glVertex2f(-1, -1);
        glTexCoord2f(1, 0);
        glVertex2f(1, -1);
        glTexCoord2f(1, 1);
        glVertex2f(1, 1);
        glTexCoord2f(0, 1);
        glVertex2f(-1, 1);
        glEnd();
 
        glPopMatrix();
        glMatrixMode(GL_PROJECTION);
        glPopMatrix();
        glMatrixMode(GL_MODELVIEW);
        glPopMatrix();
    }
 
public:
 
    void create(GLint width, GLint height, GLfloat quality = 1)
    {
        m_width = width;
        m_height = height;
        m_quality = quality;
        m_fbo_width = width * quality + 0.5f;
        m_fbo_height = height * quality + 0.5f;
        create_shader();
        create_textures();
        create_fbo();
    }
 
    void resize(GLint width, GLint height, float quality)
    {
        if (m_width == width && m_height == height && m_quality == quality)
            return;
 
        m_width = width;
        m_height = height;
        m_quality = quality;
        m_fbo_width = m_width * m_quality + 0.5f;
        m_fbo_height = m_height * m_quality + 0.5f;
 
        save_texture_state();
        save_renderbuffer_state();
 
        for (auto texture : m_textures)
        {
            glBindTexture(GL_TEXTURE_2D, texture);
            glTexImage2D(GL_TEXTURE_2D,
                         0,
                         GL_RGBA,
                         m_fbo_width,
                         m_fbo_height,
                         0,
                         GL_RGBA,
                         GL_UNSIGNED_BYTE,
                         nullptr);
        }
 
        glBindRenderbuffer(GL_RENDERBUFFER, m_stencil);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX, m_fbo_width, m_fbo_height);
 
        restore_texture_state();
        restore_renderbuffer_state();
    }
 
    void begin_draw()
    {
        save_depth_stencil_state();
        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_NOTEQUAL, 0x01, 0xff);
        glStencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
        glStencilMask(0xff);
        glDisable(GL_DEPTH_TEST);
 
        save_logic_op_state();
        glEnable(GL_COLOR_LOGIC_OP);
        glLogicOp(GL_SET);
 
        save_viewport_state();
        glViewport(0, 0, m_fbo_width, m_fbo_height);
 
        save_framebuffer_state();
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
        
    }
 
    void end_draw()
    {
        restore_depth_stencil_state();
        restore_logic_op_state();
        restore_viewport_state();
        restore_framebuffer_state();
    }
 
    void blur(float r, float g, float b)
    {
        save_depth_stencil_state();
        glDisable(GL_DEPTH_TEST);
        glDisable(GL_STENCIL_TEST);
 
        save_blend_state();
        glDisable(GL_BLEND);
 
        save_viewport_state();
        glViewport(0, 0, m_fbo_width, m_fbo_height);
 
        save_shader_state();
        glUseProgram(m_shader);
        glUniform2f(m_delta_location, 1.0f / m_fbo_width, 1.0 / m_fbo_height);
        glUniform2f(m_direction_location, 1, 0);
        glUniform1i(m_texture_location, 0);
 
        save_texture_state();
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, m_textures[0]);
 
        save_framebuffer_state();
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
        glFramebufferTexture2D(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[1], 0);
 
        draw_quad();
 
        glBindTexture(GL_TEXTURE_2D, m_textures[1]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[0], 0);
        glUniform2f(m_direction_location, 0, 1);
        
        draw_quad();
 
        glBindTexture(GL_TEXTURE_2D, m_textures[0]);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[1], 0);
 
        glUseProgram(0);
        glEnable(GL_STENCIL_TEST);
        glStencilFunc(GL_NOTEQUAL, 0x01, 0xff);
        glStencilMask(0);
        
        save_clear_color_state();
        glClearColor(0, 0, 0, 0);
        glClear(GL_COLOR_BUFFER_BIT);
 
        draw_quad();
 
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_textures[0], 0);
        glClearStencil(0);
        glStencilMask(0xff);
        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
        restore_clear_color_state();
        restore_framebuffer_state();
        restore_viewport_state();
 
        glBindTexture(GL_TEXTURE_2D, m_textures[1]);
        glDisable(GL_STENCIL_TEST);
        glEnable(GL_BLEND);
        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        
        draw_quad(r, g, b);
        
        restore_depth_stencil_state();
        restore_blend_state();
        restore_shader_state();
        restore_texture_state();
    }
};


Логика использования:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// инициализация
test ctx;
// ширина и высота фреймбуфера игры
// и качество обводки
// (пока обойдись диапазоном 0.3..1.0, по умолчанию 1.0)
ctx.create(w, h/*, q*/);
 
 
// перехват рисования объекта
ctx.begin_draw();
// call list
ctx.end_draw();
 
 
// окончательная обработка и заливка в конце кадра
ctx.blur(1, 1, 1);
 
 
// если изменился размер фреймбуфера игры
// или нужно изменить качество
ctx.resize(w, h, q);
1
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
01.12.2022, 00:01  [ТС]
zayats80888, Модельки сущностей перестали рисоваться и силуэт проявляется почему-то только в одном месте (где белое)

Вот как сделал:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int WINAPI mySwapBuffers(HDC pDeviceContextHandle)
{
    /* Getting OpenGL function pointers */
    const static int version = gladLoaderLoadGL();
 
    if (!version)
        return fpSwapBuffers(pDeviceContextHandle);
 
    if (!ctx)
    {
        ctx = new test();
        ctx->create(1280, 720);
    }
 
    int viewport[4] = {};
    glGetIntegerv(GL_VIEWPORT, viewport);
    ctx->resize(viewport[2], viewport[3], 1);
 
    ctx->blur(1, 1, 1);
 
    return fpSwapBuffers(pDeviceContextHandle);
}
 
void WINAPI myglCallList(GLuint list)
{
    if (!ctx)
        return;
 
    ctx->begin_draw();
    fpglCallList(list);
    ctx->end_draw();
}
Миниатюры
Обводка объекта с использованием шейдера  
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
01.12.2022, 00:08  [ТС]
При добавлении второго glCallList модельки сущностей появляются но никакой обводки нет
Миниатюры
Обводка объекта с использованием шейдера  
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
01.12.2022, 00:10
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Модельки сущностей перестали рисоваться
Ну так их надо рисовать, ты же только в ctx рисуешь, поэтому и исчезли.
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
силуэт проявляется почему-то только в одном месте (где белое)
Это обводка, походу, я на скрине не вижу, сделай другой цвет(красный, например, ctx->blur(1, 0, 0);
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
ctx->resize(viewport[2], viewport[3], 1);
Это желательно делать после blur, т.к. текстуры разрушает. А лучше вообще убери, я там забыл очистку добавить.
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
01.12.2022, 00:15  [ТС]
Если быстро клацать кнопку приближения то можно заметить какую-то обводку
Вложения
Тип файла: mp4 2022-12-01 00-12-07 (online-video-cutter.com).mp4 (1.57 Мб, 9 просмотров)
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
01.12.2022, 00:17  [ТС]
zayats80888,

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
int WINAPI mySwapBuffers(HDC pDeviceContextHandle)
{
    /* Getting OpenGL function pointers */
    const static int version = gladLoaderLoadGL();
 
    if (!version)
        return fpSwapBuffers(pDeviceContextHandle);
 
    if (!ctx)
    {
        ctx = new test();
        ctx->create(1280, 720);
    }
 
    ctx->blur(1, 0, 0);
    return fpSwapBuffers(pDeviceContextHandle);
}
 
void WINAPI myglCallList(GLuint list)
{
    if (!ctx)
        return;
 
    fpglCallList(list);
    ctx->begin_draw();
    fpglCallList(list);
    ctx->end_draw();
}
Миниатюры
Обводка объекта с использованием шейдера  
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
01.12.2022, 00:20
eXpl01TeR, у тебя там земля и небо через CallList рисуется, и возможно еще что-то.
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
01.12.2022, 00:29  [ТС]
zayats80888, Да.. Отключил все что мог, теперь немного изменилось.
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
01.12.2022, 00:30  [ТС]
zayats80888,
Вложения
Тип файла: mp4 2022-12-01 00-28-32 (online-video-cutter.com).mp4 (1.31 Мб, 14 просмотров)
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
01.12.2022, 00:36
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
2022-12-01 00-28-32 (online-video-cutter.com).mp4 (1.31 Мб, 0 просмотров)
XD, шляпа какая-то непонятная.

Короче, чтоб глянуть что там рисуется в трафарет, временно замени реализацию функции blur на это:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
        save_texture_state();
        save_depth_stencil_state();
        save_blend_state();
        save_framebuffer_state();
        save_clear_color_state();
        save_viewport_state();
 
        glEnable(GL_TEXTURE_2D);
        glBindTexture(GL_TEXTURE_2D, m_textures[0]);
        
        glDisable(GL_STENCIL_TEST);
        glDisable(GL_DEPTH_TEST);
        glEnable(GL_BLEND);
        glBlendEquation(GL_FUNC_ADD);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
 
        draw_quad(r, g, b);
        
        glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_fbo);
        glViewport(0, 0, m_fbo_width, m_fbo_height);
        glClearColor(0, 0, 0, 0);
        glClearStencil(0);
        glStencilMask(0xff);
        glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
        
        restore_texture_state();
        restore_depth_stencil_state();
        restore_blend_state();
        restore_framebuffer_state();
        restore_clear_color_state();
        restore_viewport_state();
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
01.12.2022, 00:36

Создание текста с использованием DrawString и обводка
Подскажите, пожалуйста, как создать такой текст с обводкой, например буква, как буква «T» на картинке ниже. Для создания текста использую...

Создать проект, с использованием объекта Timer, перемещение графического объекта по заданной траектории, (прямоугольник,
Создать проект, с использованием объекта Timer, перемещение графического объекта по заданной траектории, (прямоугольник, квадрат или...

Перемещение объекта по форме с использованием мыши
Всем доброго времени суток. Необходимо осуществить перемещение Image при помощи мыши. Объекты находятся в Canvas. Проблема заключена в...

Задача с использованием объекта hScrollBar и pictureBox
Может мой вопрос покажется глупым, но всё же...Как можно осуществить изменение размера объекта pictureBox используя hScrollBar? У меня была...

Поворот объекта с использованием Rigidbody.MoveRotation
использую Rigidbody.MoveRotation для поворота объекта по оси Х на 30 градусов, проблема в том что оно НЕ затухает при 30 градусов, а просто...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
160
Ответ Создать тему
Новые блоги и статьи
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
Установка MinGW GCC 16.2 и CMake
8Observer8 10.08.2026
VK Видео: https:/ / vkvideo. ru/ video-240781534_456239017 YouTube: eY5-5PyI9NM Текстовая версия
Неделя из жизни имитационной модели склада: мои кривые руки растут, откуда надо
anaschu 10.08.2026
Неделя из жизни имитационной модели склада: как я почти написал неправильную логику и что с этим делать Работаю сейчас над учебно-рабочим проектом: строю в AnyLogic имитационную модель процессов. . .
Калькулятор для расчета родства
russiannick 07.08.2026
1. Задача: Создать калькулятор для расчета родства. Родственных связей существует 8 ступеней, такие как: p - отец P - мать q - муж Q - жена b - брат B - сестра s - сын S - дочь
Мир по моей воле
kumehtar 07.08.2026
Когда-то кажется, что всё просто. Ты весь такой светлый. Причиняешь добро. Борешься за справедливость в этом тёмном мире. Потом начинаешь замечать одну неприятную вещь. Почти каждый хороший. . .
Кредитный калькулятор
Maks 05.08.2026
Решение задачи по прикладной информатике средствами 1С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru