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

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

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

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

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

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

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

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

180
08.10.2021, 23:33
Студворк — интернет-сервис помощи студентам

Не по теме:

Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Я выкладывал так же ссылку на imgur где изображения без сжатия но к сожалению модератор счёл нужным её удалить
А мог ведь переписать это в читаемый код, заменив все "магические" числа на дефайны OpenGL и числовые константы. Но нет, вывалил как есть, даже обрезать 90% ненужной информации поленился.

0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
09.10.2021, 12:27
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
  // как пользоваться шейдерами ты знаешь,
  // поэтому я спрячу эти детали в класс,
  // чтобы не захламлять (гомно)код
  gl::Program blur;
  {
    gl::Shader frag{gl::ShaderType::Fragment};
    const std::string srcFrag = R"(
      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(color);
      }
    )";
    frag.loadFromMemory(srcFrag);
    blur.attachShader(frag);
    blur.link();
  }
 
  GLint uDirection = blur.getUniformLocation("uDirection");
  GLint uDelta = blur.getUniformLocation("uDelta");
  
  // размеры кастомных текстур должны иметь то же соотношение сторон,
  // что и основной фрэймбуфер окна, но для повышения производительности и экономии памяти
  // путём снижения качества, можно их пропорционально уменьшить
  GLint fboSizeX = 800;
  GLint fboSizeY = 600;
  // две текстуры для фрэймбуфера
  GLuint tex[2] = {};
  gl->GenTextures(2, tex);
  for (auto texture : tex) {
    gl->BindTexture(GL_TEXTURE_2D, texture);
    gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    // на самом деле тут достаточно одноканальных текстур,
    // но мне лень пихать ещё один шейдер для заливки обводки,
    // так что будем использовать фиксированный конвейер и RGBA текстуры
    gl->TexImage2D(GL_TEXTURE_2D,
                   0,
                   GL_RGBA,
                   fboSizeX,
                   fboSizeY,
                   0,
                   GL_RGBA,
                   GL_UNSIGNED_BYTE,
                   nullptr);
  }
  gl->BindTexture(GL_TEXTURE_2D, 0);
  // фрэймбуфер
  GLuint fbo = 0;
  gl->GenFramebuffers(1, &fbo);
  gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
  gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
  GLenum status = gl->CheckFramebufferStatus(GL_FRAMEBUFFER);
  if (status != GL_FRAMEBUFFER_COMPLETE) {
    utils::message(utils::LogType::Critical, "incomplete fbo");
  }
  gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
 
  gl->GenLists(2);
  // создаём call list для куба с цветными гранями
  gl->NewList(1, GL_COMPILE);
  {
    const double a = 1.0;
    const vec3 ltf = {-a, a, -a};
    const vec3 lbf = {-a, -a, -a};
    const vec3 rbf = {a, -a, -a};
    const vec3 rtf = {a, a, -a};
    const vec3 ltn = {-a, a, a};
    const vec3 lbn = {-a, -a, a};
    const vec3 rbn = {a, -a, a};
    const vec3 rtn = {a, a, a};
    
    gl->Begin(GL_QUADS);
 
    gl->Color3d(0.8, 0.2, 0.2);
    gl->Vertex3dv(ltf.data());
    gl->Vertex3dv(lbf.data());
    gl->Vertex3dv(lbn.data());
    gl->Vertex3dv(ltn.data());
    gl->Color3d(0.8, 0.8, 0.2);
    gl->Vertex3dv(ltn.data());
    gl->Vertex3dv(lbn.data());
    gl->Vertex3dv(rbn.data());
    gl->Vertex3dv(rtn.data());
    gl->Color3d(0.2, 0.8, 0.2);
    gl->Vertex3dv(rtn.data());
    gl->Vertex3dv(rbn.data());
    gl->Vertex3dv(rbf.data());
    gl->Vertex3dv(rtf.data());
    gl->Color3d(0.2, 0.8, 0.8);
    gl->Vertex3dv(rtf.data());
    gl->Vertex3dv(rbf.data());
    gl->Vertex3dv(lbf.data());
    gl->Vertex3dv(ltf.data());
    gl->Color3d(0.2, 0.2, 0.8);
    gl->Vertex3dv(ltf.data());
    gl->Vertex3dv(ltn.data());
    gl->Vertex3dv(rtn.data());
    gl->Vertex3dv(rtf.data());
    gl->Color3d(0.8, 0.2, 0.8);
    gl->Vertex3dv(lbn.data());
    gl->Vertex3dv(lbf.data());
    gl->Vertex3dv(rbf.data());
    gl->Vertex3dv(rbn.data());
    
    gl->End();
  }
  gl->EndList();
 
  // создаём call list для текстурированного прямоугольника во весь экран
  gl->NewList(2, GL_COMPILE);
  {
    gl->PushMatrix();
    gl->LoadIdentity();
    gl->MatrixMode(GL_PROJECTION);
    gl->PushMatrix();
    gl->LoadIdentity();
    gl->MatrixMode(GL_TEXTURE);
    gl->PushMatrix();
    gl->LoadIdentity();
 
    gl->Begin(GL_QUADS);
    gl->TexCoord2d(0.0, 0.0);
    gl->Vertex2d(-1.0, -1.0);
    gl->TexCoord2d(1.0, 0.0);
    gl->Vertex2d(1.0, -1.0);
    gl->TexCoord2d(1.0, 1.0);
    gl->Vertex2d(1.0, 1.0);
    gl->TexCoord2d(0.0, 1.0);
    gl->Vertex2d(-1.0, 1.0);
    gl->End();
 
    gl->PopMatrix();
    gl->MatrixMode(GL_PROJECTION);
    gl->PopMatrix();
    gl->MatrixMode(GL_MODELVIEW);
    gl->PopMatrix();
  }
  gl->EndList();
  
  // рисование кубика
  // scale - масштаб
  // off - смещение
  // angle - угол поворота
  // axis - ось, вокруг которой поворачиваем
  auto cube = [gl](double scale, vec3 const& off, double angle, vec3 const& axis) {
    gl->PushMatrix();
 
    gl->Rotated(angle, axis[0], axis[1], axis[2]);
    gl->Translated(off[0], off[1], off[2]);
    gl->Rotated(angle * 0.5, axis[1], axis[2], axis[0]);
    gl->Scaled(scale, scale, scale);
 
    gl->CallList(1);
 
    gl->PopMatrix();
  };
 
  // перспективная проекция
  gl->MatrixMode(GL_PROJECTION);
  gl->LoadIdentity();
  gl->Frustum(-4, 4, -3, 3, 10, 100);
 
  // положение "камеры"
  gl->MatrixMode(GL_MODELVIEW);
  gl->LoadIdentity();
  gl->Translated(0.0, 0.0, -25.0);
 
  gl->Viewport(0, 0, 800, 600);
  
  gl->Enable(GL_DEPTH_TEST);
  gl->Enable(GL_CULL_FACE);
  gl->CullFace(GL_BACK);
 
  while (!glfwWindowShouldClose(window)) {
    glfwPollEvents();
////////////////////////////////////////////////////////////////////////////////
    double t = glfwGetTime();
    double angle = t * 30.0;
 
    gl->ClearColor(0.3f, 0.73f, 0.91f, 1.0f);
    gl->Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
    // Рисуем два маленьких кубика.
    // При этом в трафарете выставляем младший бит,
    // вне зависимости от успеха теста глубины(чтоб и за "стенками" было видно).
    gl->Enable(GL_STENCIL_TEST);
    gl->StencilFunc(GL_ALWAYS, 0x01, 0xff);
    gl->StencilOp(GL_KEEP, GL_REPLACE, GL_REPLACE);
    cube(1.0, vec3{3.0, 3.0, 3.0}, angle, vec3{-1.0, 1.0, 0.0});
    cube(1.0, vec3{4.0, 5.0, 6.0}, angle, vec3{-1.0, 1.0, 0.0});
    gl->Disable(GL_STENCIL_TEST);
 
    // Опять рисуем два маленьких кубика, но в нашу текстуру
    // крася фрагменты в белый цвет
    gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
    gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
    gl->Viewport(0, 0, fboSizeX, fboSizeY);
    gl->ClearColor(0, 0, 0, 0);
    gl->Clear(GL_COLOR_BUFFER_BIT); // очищать нужно только один раз за кадр
    gl->Enable(GL_COLOR_LOGIC_OP);
    gl->LogicOp(GL_SET); // красим в белый цвет
    cube(1.0, vec3{3.0, 3.0, 3.0}, angle, vec3{-1.0, 1.0, 0.0});
    cube(1.0, vec3{4.0, 5.0, 6.0}, angle, vec3{-1.0, 1.0, 0.0});
    gl->Disable(GL_COLOR_LOGIC_OP);
    gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
    gl->Viewport(0, 0, 800, 600);
 
    // Рисуем большой кубик (ну или просто остальные объекты сцены)
    cube(2.2, vec3{}, 0.3 * angle, vec3{1.0, 0.0, 1.0});
 
    // теперь делаем обводку
    // делать это нужно один раз в конце рисования сцены
 
    // блюрим силуэты (блюр в два прохода)
    gl->Enable(GL_TEXTURE_2D);
    blur.bind();
    blur.setUniform(uDelta, gl::vec2{1.0f/fboSizeX, 1.0f/fboSizeY});
    gl->BindFramebuffer(GL_FRAMEBUFFER, fbo);
    gl->Viewport(0, 0, fboSizeX, fboSizeY);
    gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[1], 0);
    gl->BindTexture(GL_TEXTURE_2D, tex[0]);
    blur.setUniform(uDirection, gl::vec2{1.0f, 0.0f});
    gl->CallList(2);
    gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex[0], 0);
    gl->BindTexture(GL_TEXTURE_2D, tex[1]);
    blur.setUniform(uDirection, gl::vec2{0.0f, 1.0f});
    gl->CallList(2);
    blur.unbind();
    // заливаем цветом экран там,
    // где в буфере трафарета не выставлен младший бит
    // и есть размытые силуэты объектов
    gl->BindFramebuffer(GL_FRAMEBUFFER, 0);
    gl->Viewport(0, 0, 800, 600);
    gl->BindTexture(GL_TEXTURE_2D, tex[0]);
    gl->Enable(GL_BLEND);
    gl->BlendEquation(GL_FUNC_ADD);
    gl->BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    gl->Enable(GL_STENCIL_TEST);
    gl->Disable(GL_DEPTH_TEST);
    gl->StencilFunc(GL_NOTEQUAL, 0x01, 0xff);
    gl->StencilMask(0x00);
    double a = (std::sin(std::fmod(t * 2.0, 6.2832)) + 1.0) * 0.5;
    gl->Color3d(a, a, a);
    gl->CallList(2);
    gl->StencilMask(0xff);
    gl->Disable(GL_STENCIL_TEST);
    gl->Disable(GL_BLEND);
    gl->Enable(GL_DEPTH_TEST);
    gl->Disable(GL_TEXTURE_2D);
    
    
////////////////////////////////////////////////////////////////////
    glfwSwapBuffers(window);
  }
 
  gl->DeleteLists(1, 2);
  gl->DeleteFramebuffers(1, &fbo);
  gl->DeleteTextures(2, tex);


В игре тебе нужно будет следить за состояниями контекста, т.к. ты их не контролируешь.

И как это выглядит:
Вложения
Тип файла: zip exploiter_test.zip (725.5 Кб, 37 просмотров)
1
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
11.10.2021, 23:19  [ТС]

Не по теме:

zayats80888, Я сгенерировал заголовочный файл для OpenGL 3.0 Core Profile но там есть функции glVertex / glBegin, это нормально? Я думал этих функций там быть не должно. Их лучше не использовать или как?



Цитата Сообщение от zayats80888 Посмотреть сообщение
вот фрагмент упрощенного гомнокода с обводкой размытием:
Пока ещё не пробовал, но спасибо большое. По идее просто сохранять call-листы и вызывать их при SwapBuffers пойдет? Или надо будет ещё и состояния матриц возвращать?
Вложения
Тип файла: 7z GL.7z (30.5 Кб, 18 просмотров)
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
11.10.2021, 23:27
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
это нормально?
Да, нормально.
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Их лучше не использовать или как?
Если контекст не forward compat, то можешь использовать(иначе, они просто ничего не делают, а только генерируют ошибки GL_INVALID_OPERATION)
В обоих примерах, что я скидывал, то же loader для OpenGL 3.0, если что.
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
По идее просто сохранять call-листы и вызывать их при SwapBuffers пойдет? Или надо будет ещё и состояния матриц возвращать?
call-листы игры ты должен вызывать там же, где и игра их вызывает, с учетом матриц. Свой call-лист c прямоугольником(если будешь использовать, у меня в примере с индексом 2) ты вызываешь только в SwapBuffers, где делаешь размытие и обводку с наложением.
0
11.10.2021, 23:36  [ТС]

Не по теме:

Цитата Сообщение от zayats80888 Посмотреть сообщение
вот фрагмент упрощенного гомнокода с обводкой размытием:
zayats80888, А нельзя ли как-то сгенерировать файл чтобы там были только функции для работы с шейдерами?

0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
11.10.2021, 23:42
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
А нельзя ли как-то сгенерировать файл чтобы там были только функции для работы с шейдерами?
Всмысле? Тебе классы gl::Shader и gl::Program из моего примера нужны? Или что? (ты же вроде сам шейдеры создавал уже...)
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
11.10.2021, 23:46  [ТС]

Не по теме:

Цитата Сообщение от zayats80888 Посмотреть сообщение
Тебе классы gl::Shader и gl::Program из моего примера нужны? Или что?
Не, меня просто напрягает что в файле сгенерированном для Core 3.0 есть функции для работы с фиксированным конвейером (или как там это называется) Я думал при генерации файла для Core 3.0 будут функции только для работы с шейдерами ибо там уже от них "отказались" (я так думал)



Добавлено через 1 минуту

Не по теме:

Цитата Сообщение от zayats80888 Посмотреть сообщение
ты же вроде сам шейдеры создавал уже...
А вот и нет. Я копипастил код с сайта по созданию треугольника и немного лишь переделывал фрагментный. А то как они работают я до сих пор не понимаю. Я пока даже не занимался созданием шейдера для отрисовки тех прямоугольников.

0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
11.10.2021, 23:53
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Не, меня просто напрягает что в файле сгенерированном для Core 3.0 есть функции для работы с фиксированным конвейером
Ну так у тебя игра с ним(фикс. конвейером) работает. И я уже устал повторять, нет никакого Сore и Compatible до 3.2
0
155 / 9 / 2
Регистрация: 14.08.2019
Сообщений: 771
12.10.2021, 19:32  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
Ну так у тебя игра с ним(фикс. конвейером) работает
Я же говорил, старые версии игры работают с фиксированным конвейером, но новая (которая недавно вышла и обновилась до нового OpenGL) нет! Там все на шейдерах!

Добавлено через 9 минут
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Там все на шейдерах!
И по этому ты мне посоветовал использовать шейдеры для рисования менюшки (кубики там всякие)
0
12.10.2021, 19:33

Не по теме:

Цитата Сообщение от eXpl01TeR Посмотреть сообщение
но новая (которая недавно вышла и обновилась до нового OpenGL) нет! Там все на шейдерах!
Ну так и в чем проблема?

0
12.10.2021, 19:58  [ТС]

Не по теме:

Цитата Сообщение от zayats80888 Посмотреть сообщение
Ну так и в чем проблема?
Проблема в том что мне придется каждый раз тестировать программу на обеих версиях игры из-за того что в файле GL.h есть функции для работы с фиксированным конвейером (или как он там называется) и я могу по незнанию воспользоваться одной из них - _____-

0
12.10.2021, 20:08

Не по теме:

Цитата Сообщение от eXpl01TeR Посмотреть сообщение
и я могу по незнанию воспользоваться одной из них - _____-
Ну сгенерируй себе для 3.2 core, потом подсунь 3.0(для проверки, что не дернул чего лишнего из поздней версии) или наоборот. Это проверка на этапе компиляции.
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Проблема в том что мне придется каждый раз тестировать программу на обеих версиях игры
Тебе это в любом случае делать, т.к. игра использует разный функционал, тебе разные функции перхватывать и реализовывать разную логику.

0
12.10.2021, 20:17  [ТС]

Не по теме:

Цитата Сообщение от zayats80888 Посмотреть сообщение
Тебе это в любом случае делать, т.к. игра использует разный функционал, тебе разные функции перхватывать и реализовывать разную логику.
Так ты же сам говорил что шейдеры подойдут в любом случае если использовать только функции из Core 3.0

0
12.10.2021, 20:19

Не по теме:

Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Так ты же сам говорил что шейдеры подойдут в любом случае если использовать только функции из Core 3.0
Не выдумывай. Ссылку на мой пост со словами "в любом случае". И причем тут шейдеры и о каких шейдерах ты говоришь?

0
12.10.2021, 20:29  [ТС]

Не по теме:

zayats80888, Как убрать мерцание overlay?

0
12.10.2021, 20:35

Не по теме:

eXpl01TeR, ну и где ты там увидел "в любом случае"? И какое это имеет отношение к функционалу игры? Там речь про твоё рисование в совместимый контекст, а не про то, как игра рисует.

0
12.10.2021, 20:45  [ТС]

Не по теме:

Цитата Сообщение от zayats80888 Посмотреть сообщение
Там речь про твоё рисование в совместимый контекст, а не про то, как игра рисует.
Так я и говорю про своё рисование.. Ладно, проехали ._.

0
9987 / 2959 / 497
Регистрация: 05.10.2013
Сообщений: 8,102
Записей в блоге: 243
14.10.2021, 13:46
Цитата Сообщение от eXpl01TeR Посмотреть сообщение
Это при рисовании с шейдером или без? Я нашел какой-то ролик на YouTube, пробую, но пока не очень выходит.
Я делал по этому видео уроку, у меня получилось. Там почти тоже самое, что и в этом текстовом уроке:

Цитата Сообщение от zayats80888 Посмотреть сообщение
В видео уроке решается проблема с масштабами выделения, которыми забиты комментарии в learnopengl. Кстати, у текстового урока есть перевод на русский: Learn OpenGL. Часть 4.2. — Тест трафарета. Я, правда, русский перевод не изучал, поэтому не знаю какое у него качество.

По этим урокам, если оба объекта выделены, то смотрится нормально:



Но, если передний объект не выделен, то получается такая проблема:



zayats80888, не подскажете, как эту проблему решить без явного использования Frame Buffer, только силами Stencil Buffer? Мне хочется, чтобы было видно только обводку сквозь другой объект, как у вас в демке.

Можно закомментировать отключение буфера глубины, тогда проблема почти решается:



У меня в инициализации такой код:

C++ (Qt)
1
2
3
4
5
6
7
void OpenGLWidget::initializeGL()
{
    glClearColor(0.2f, 0.2f, 0.2f, 1.f);
    glEnable(GL_DEPTH_TEST);
    glEnable(GL_STENCIL_TEST);
    glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
При рисовании такой:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void OpenGLWidget::paintGL()
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 
    _projViewMatrix = _projMatrix * _viewMatrix;
 
    glStencilMask(0x00);
    _ground->draw(&_projViewMatrix);
    _tree->draw(&_projViewMatrix);
 
    glStencilFunc(GL_ALWAYS, 1, 0xFF);
    glStencilMask(0xFF);
    _house->draw(&_projViewMatrix);
 
    glStencilFunc(GL_NOTEQUAL, 1, 0xFF);
    glStencilMask(0x00);
    glDisable(GL_DEPTH_TEST);
    _houseOutline->draw(&_projViewMatrix);
//    _treeOutline->draw(&_projViewMatrix);
0
 Аватар для zayats80888
6353 / 3524 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
14.10.2021, 14:58
Цитата Сообщение от 8Observer8 Посмотреть сообщение
Мне хочется, чтобы было видно только обводку сквозь другой объект, как у вас в демке.
На этот вопрос я ответил в посте #33. Вам нужно при "провале" теста глубины тоже писать в буфер трафарета (второй параметр функции glStencilOp).
1
9987 / 2959 / 497
Регистрация: 05.10.2013
Сообщений: 8,102
Записей в блоге: 243
14.10.2021, 15:10
Цитата Сообщение от zayats80888 Посмотреть сообщение
На этот вопрос я ответил в посте #33. Вам нужно при "провале" теста глубины тоже писать в буфер трафарета (второй параметр функции glStencilOp).
Огромное спасибо! Вы меня очень сильно выручили. Я почти понял, как работает трафарет, но "почти" не считается.
Миниатюры
Обводка объекта с использованием шейдера  
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
14.10.2021, 15:10

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
100
Ответ Создать тему
Новые блоги и статьи
Часы электронные
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С. Задача: Напишите приложение-калькулятор, которое помогает рассчитывать параметры кредита для аннуитетного и дифференцированного видов. . .
У нас сейчас поговорку "Опять 25" нужно переделать на "Опять +35".
kumehtar 04.08.2026
С ностальгией вспоминаю времена моего детства, когда у нас и правда +25 - была максимальная температура летом. Раньше +25 °C реально казались вершиной жары, когда можно было весь день пропадать на. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru