Форум программистов, компьютерный форум, киберфорум
Программирование графики
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/11: Рейтинг темы: голосов - 11, средняя оценка - 4.91
 Аватар для NANO_VIRUS
18 / 18 / 8
Регистрация: 19.09.2015
Сообщений: 47

Буфер трафарета

21.02.2021, 16:26. Показов 2388. Ответов 12

Студворк — интернет-сервис помощи студентам
Здравствуйте.
Проблема такая, что я не могу понять как работает этот буфер. Смотрел много видео и текстовых уроков. Но никто нормально объяснить не может, либо я такой чайник.

Вот примерно задачу, которую я хочу решить (для понимания)

Все рисуем на 2д проекции буфер глубины отключен и мы его не используем

Есть квадрат с текстурой кирпича, мне нужно окрасить его в зеленый и вырезать из него форму синего кирпича

То есть порядок такой
1. Рисуется квадрат с текстурой,(Можно просто квадрат с цветом, но его нужно в следующем шаге перекрасить)
2. Очищаем весь фон в зеленый цвет, при этом буфер трафарета должен его очистить только в области квадрата с текстурой.
3. Рисуем синий квадрат, который после через буфер трафарета исчезает и вырезает, уже у зеленого квадрата своей формой отверстие

Если можете объясните в каком порядке это правильно рисовать и что происходит в этот момент со всеми значениями ref и mask и в самом буфере. Чтобы уже наконец понять как это работает.
Возможно это нельзя сделать в три этапа. Так как разукрасить квадрат отдельно я смог и то на угад(примерами из интернета) без понятия как это произошло, и отдельно сделать вырез.

В заранее спасибо
Миниатюры
Буфер трафарета  
0
Лучшие ответы (1)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
21.02.2021, 16:26
Ответы с готовыми решениями:

Буфер кадра, буфер трафарета и буфер глубины
Здравствуйте, Я никак не могу найти информацию о том, что такое буфер кадра, буфер трафарета и буфер глубины. Что они из себя...

Буфер трафарета
Есть какое-то тело, например, цилиндр, разбитое на треугольники (тесселированное). Хочу нарисовать только контур тела. Пытаюсь...

Буфер трафарета для сцены с несколькими объектами
Сделать вырез в фигуре с использованием буфера трафарета несложно, в сети примеров хватает. Но что-то у меня некорректно работает для...

12
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
21.02.2021, 18:16
NANO_VIRUS,
1) очищаешь буфер трафарета
2) рисуешь квадрат с текстурой, в трафарет пишешь 66(или что угодно)
3) рисуешь синий квадрат, в трафарет пишешь что угодно, кроме 66(или что ты там писал).
4) рисуешь зелёный квадрат на весь экран с тестом трафарета на 66(или что ты там писал).

Добавлено через 2 минуты
Непонятны трафареты - новичек
1
 Аватар для NANO_VIRUS
18 / 18 / 8
Регистрация: 19.09.2015
Сообщений: 47
21.02.2021, 20:25  [ТС]
Спасибо большое что ответили. Там где вы оставили ссылку на такой же вопрос. Я посмотрел, но все равно не смог вникнуть. Наверное мне нужно разжувать более конкретней. Так как считаю, что какую-то часть я понял, а какую то нет. То примерно опишу пример более низкой части, так как я не могу все это представить.
Если вам будет не трудно, сможете мне объяснить принцип работы в таком порядке.

Я переделал пример под ваш вариант. На картинке каждый этап отделен черной линией с цифрой этапа.

Могу попросить вас написать примерное в таком виде. Если не трудно конечно.
Какие значения (mask, ref) должны стоять либо перед рисованием квадрата либо после, а так же какое условие нужно поставить и как это должно повлиять на сам буфер.



--Очищение буфера
1. этап.

условие = ??? (например EQUAL)
ref = ???
mask = ???
что делаем по условию = ??? (например KEEP)
рисуем

2. этап (что поменялось в буфере(ref, mask))

условие = ??? (например EQUAL)
ref = ???
mask = ???
что делаем по условию = ??? (например KEEP)
рисуем синий квадрат

3. этап (что поменялось в буфере(ref, mask))

условие = ??? (например EQUAL)
ref = ???
mask = ???
рисуем зеленый фон
что делаем по условию = ??? (например KEEP)

Да это может выглядеть абсурдно. Но я правда не могу найти оптимального объяснения для себя и готов что говориться заново учиться считать по палочкам на столе.. И лучше всего со всеми тремя этапами, так как считаю что лучше пойму суть понимая разницу между ними
Изображения
 
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
21.02.2021, 20:41
NANO_VIRUS,
1) очищение буфера
Code
1
2
glStencilMask(0xFF);
glClear(...);
2) квадрат с текстурой
Code
1
2
3
4
glStencilMask(0xFF);
glStencilFunc(GL_ALWAYS, 66, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glDraw...
3) синий квадрат(в вашем случае лучше сразу белый)
Code
1
2
3
4
glStencilMask(0xFF);
glStencilFunc(GL_ALWAYS, 0, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);
glDraw...
4) зелёный квадрат на весь экран
Code
1
2
3
4
glStencilMask(0xFF); // на самом деле пофиг, можно поставить маску записи 0x00, что бы не менять glStencilOp
glStencilFunc(GL_EQUAL, 66, 0xFF);
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDraw...
Разумеется состояние, которое не меняется с предыдущего этапа трогать не нужно, я просто для наглядности всё писал
1
 Аватар для NANO_VIRUS
18 / 18 / 8
Регистрация: 19.09.2015
Сообщений: 47
22.02.2021, 10:31  [ТС]
Спасибо, что помогаете.
У меня ваш код, сработал частично, синий квадрат не вырезает. У меня фон может быть разным, не обязательно белым, это чисто для примера.
Я работаю в одно игре где используется обертка под графику. Думал сначала в этом проблема. Но потом перенес все в webgl, и там все та-же проблема.

Для удобства сделал аналог webgl на codepen
весь основной код с трафаретами из вашего примера начинается на 133 строке js кода.
Синтаксис даже не нужно знать, только выставлять параметры.
https://codepen.io/envoleon/pen/KKNXaOq
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
22.02.2021, 15:16
Цитата Сообщение от NANO_VIRUS Посмотреть сообщение
синий квадрат не вырезает
Я же писал,
Цитата Сообщение от zayats80888 Посмотреть сообщение
в вашем случае лучше сразу белый
Цитата Сообщение от NANO_VIRUS Посмотреть сообщение
У меня фон может быть разным, не обязательно белым, это чисто для примера.
Тогда добавьте 5 этап - отрисовку фона:
5) рисуем фон
Code
1
2
3
4
glStencilMask(0xFF);
glStencilFunc(GL_NOTEQUAL, 66, 0xFF); // <-------
glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
glDraw...
0
 Аватар для NANO_VIRUS
18 / 18 / 8
Регистрация: 19.09.2015
Сообщений: 47
22.02.2021, 18:25  [ТС]
Вы наверное не правильно поняли задачу.
Цитата Сообщение от NANO_VIRUS Посмотреть сообщение
Рисуем синий квадрат, который после через буфер трафарета исчезает и вырезает, уже у зеленого квадрата своей формой отверстие
Я же вроде дословно написал, что задача стоит именно вырезать. Зачем мне рисовать фон который уже нарисован? Да и вместе с фоном куча объектов может быть. Я могу вырезать объект, я могу его закрасить, но объединить оба действия не выходит.
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
22.02.2021, 18:36
Цитата Сообщение от NANO_VIRUS Посмотреть сообщение
Я же вроде дословно написал, что задача стоит именно вырезать. Зачем мне рисовать фон который уже нарисован?
Если вы поверх фона нарисуете квадрат с текстурой, то после действия "вырезать", откуда возьмутся пиксели фона? Вы их уже перезаписали своим квадратом.

Добавлено через 3 минуты
Вам нужно либо фон накладывать после, либо НЕ рисовать квадрат с текстурой и вырезающий квадрат в буфер цвета, а только в буфер трафарета, что бы потом залить зелёным(кстати, какой смысл рисовать текстурированный квадрат, если вы его заливаете зелёным?).
0
 Аватар для NANO_VIRUS
18 / 18 / 8
Регистрация: 19.09.2015
Сообщений: 47
22.02.2021, 19:03  [ТС]
Цитата Сообщение от zayats80888 Посмотреть сообщение
Вам нужно либо фон накладывать после, либо НЕ рисовать квадрат с текстурой и вырезающий квадрат в буфер цвета, а только в буфер трафарета
Поступим проще.
Я привел пример того как вырезается квадрат(для демонстрации) и обновил ссылку. Строка начала кода 137https://codepen.io/envoleon/pen/KKNXaOq
, и приложу его здесь
JavaScript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
    gl.enable(gl.STENCIL_TEST);
    
    gl.stencilMask(0xFF);
    gl.clearStencil(0);
    
    gl.bindTexture(gl.TEXTURE_2D, whiteTexture); // texture off
    
    gl.stencilMask(0xFF);
    gl.stencilFunc(gl.NEVER, 2, 0xFF);
    gl.stencilOp(gl.REPLACE, gl.KEEP, gl.REPLACE);
    DrawRectangle(gl, translation[0], translation[1], 50, 50, colorBlue);
    
    gl.bindTexture(gl.TEXTURE_2D, texInfo.texture);
    gl.stencilMask(0xFF);
    gl.stencilFunc(gl.GREATER, 1, 0xFF);
    gl.stencilOp(gl.REPLACE, gl.KEEP, gl.KEEP);
    DrawRectangleTex(gl, 0, 0, 200, 200, colorBlack);
Как мне разукрасить результат этого теста?

Цитата Сообщение от zayats80888 Посмотреть сообщение
(кстати, какой смысл рисовать текстурированный квадрат, если вы его заливаете зелёным?)
Пример чисто для понимания, никакой роли он не имеет, мне нужно чисто понять принцип работы. И так как я понял дословно мне объяснить (для себя) не получится, я придумал пример задачи в три этапа. По решению которой я буду разбирать каждый шаг.
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
22.02.2021, 19:15
Лучший ответ Сообщение было отмечено NANO_VIRUS как решение

Решение

Цитата Сообщение от NANO_VIRUS Посмотреть сообщение
Я привел пример того как вырезается квадрат(для демонстрации)
Правильно, вот тут как раз вы и не рисуете вырезающий квадрат(только в стенсил буфер рисуется).
Цитата Сообщение от NANO_VIRUS Посмотреть сообщение
gl.stencilFunc(gl.NEVER, 2, 0xFF);
gl.stencilOp(gl.REPLACE, gl.KEEP, gl.REPLACE);
Цитата Сообщение от NANO_VIRUS Посмотреть сообщение
Как мне разукрасить результат этого теста?
JavaScript
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
    gl.enable(gl.STENCIL_TEST);
    
    gl.stencilMask(0xFF);
    gl.clearStencil(0);
   // texSpace
    
    gl.bindTexture(gl.TEXTURE_2D, whiteTexture); // texture off
    
   // gl.stencilMask(0xFF);
    gl.stencilFunc(gl.NEVER, 2, 0xFF);
    gl.stencilOp(gl.REPLACE, gl.KEEP, gl.REPLACE);
    DrawRectangle(gl, translation[0], translation[1], 50, 50, colorBlue);
    
    gl.bindTexture(gl.TEXTURE_2D, texInfo.texture);
    //gl.stencilMask(0xFF);
    gl.stencilFunc(gl.GREATER, 1, 0xFF);
    gl.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
    DrawRectangleTex(gl, 0, 0, 200, 200, colorBlack);
 
 
    
    //gl.stencilMask(0xFF);
    gl.stencilFunc(gl.EQUAL, 1, 0xFF);
    gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
    DrawRectangle(gl, 0, 0, gl.canvas.width, gl.canvas.height, colorGreen);
 
    
     gl.disable(gl.STENCIL_TEST);
Добавлено через 3 минуты
PS Только если хотите чисто зелёный, то отвяжите текстуру перед заливкой gl.bindTexture(gl.TEXTURE_2D, null);
1
 Аватар для NANO_VIRUS
18 / 18 / 8
Регистрация: 19.09.2015
Сообщений: 47
22.02.2021, 19:53  [ТС]
Спасибо, попробую теперь разобрать, что к чему
Цитата Сообщение от zayats80888 Посмотреть сообщение
PS Только если хотите чисто зелёный, то отвяжите текстуру перед заливкой gl.bindTexture(gl.TEXTURE_2D, null);
Это знаю, но не имеет смысла, так как пример чисто для понимания

Еще такой не обычный вопрос
Цитата Сообщение от zayats80888 Посмотреть сообщение
Правильно, вот тут как раз вы и не рисуете вырезающий квадрат(только в стенсил буфер рисуется).
Вы написали, что рисуется в буфере трафарета. Так вот есть ли доступ к этому буферу до обработки и доступ к буферу глубины?
Представим например, что я рисую очень сложную много полигональную модель. Она провела математический расчет (по полигонам) и отобразила его внутри буфера трафарета для вырезания. Но мне нужно иметь абсолютно такую-же, но для отображения (скажем после или до, не важно). И тут нужно исключить ее двойную математическую обработку (по полигонам)

Я конечно могу нарисовать ее один раз и перевести в текстуру и работать уже с текстурой в обоих ситуациях. Но может возникнуть такая ситуация, что например, одна часть уйдет в обработку теста буфера глубины а другая должна отобразится без этого теста.
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
22.02.2021, 20:03
Буфер глубины читать можно, а трафарет вроде как нельзя(точно не помню).
1
 Аватар для NANO_VIRUS
18 / 18 / 8
Регистрация: 19.09.2015
Сообщений: 47
22.02.2021, 20:05  [ТС]
И на том спасибо
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
22.02.2021, 20:05
Помогаю со студенческими работами здесь

Как выбрать какую часть в поверхности рисовать через буфер трафарета (Stencil Buffer)?
Как описывают это разные источники, чтобы пометить что-то в буфере трафарета, нужно отключить запись в Z-буфер и основной буфер (front...

Плоское зеркало с использованием буфера трафарета
Привет всем! Подскажите где найти пример исходника плоского зеркала с исполтзованием буфера трафарета на directX.Нигде не могу...

Буфер трафарета
Добрый день! Подскажите, пожалуйста, как использовать буфер трафарета для каждой стороны тетраэдра? Вырезать планирую примерно...

Буфер трафарета
Подскажите пожалуйста, как в OpenGL реализовать следующую функциональность: 1. Создаём буфер трафарета: 111 000 000 2. Рисуем по...

Буфер трафарета, маска и с чем его едят
Добрый день друзья! Столкнулся с такой задачей. Нужно реализовать с помощью буфера трафарета, многоугольник представляющий дырку (он...


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

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Реализация движения на Box2D v3 - трение и коллизии с повёрнутыми стенами
8Observer8 20.02.2026
Содержание блога Box2D позволяет легко создать главного героя, который не проходит сквозь стены и перемещается с заданным трением о препятствия, которые можно располагать под углом, как верхнее. . .
Конвертировать закладки radiotray-ng в m3u-плейлист
damix 19.02.2026
Это можно сделать скриптом для PowerShell. Использование . \СonvertRadiotrayToM3U. ps1 <path_to_bookmarks. json> Рядом с файлом bookmarks. json появится файл bookmarks. m3u с результатом. # Check if. . .
Семь CDC на одном интерфейсе: 5 U[S]ARTов, 1 CAN и 1 SSI
Eddy_Em 18.02.2026
Постепенно допиливаю свою "многоинтерфейсную плату". Выглядит вот так: https:/ / www. cyberforum. ru/ blog_attachment. php?attachmentid=11617&stc=1&d=1771445347 Основана на STM32F303RBT6. На борту пять. . .
Камера Toupcam IUA500KMA
Eddy_Em 12.02.2026
Т. к. у всяких "хикроботов" слишком уж мелкий пиксель, для подсмотра в ESPriF они вообще плохо годятся: уже 14 величину можно рассмотреть еле-еле лишь на экспозициях под 3 секунды (а то и больше),. . .
И ясному Солнцу
zbw 12.02.2026
И ясному Солнцу, и светлой Луне. В мире покоя нет и люди не могут жить в тишине. А жить им немного лет.
«Знание-Сила»
zbw 12.02.2026
«Знание-Сила» «Время-Деньги» «Деньги -Пуля»
SDL3 для Web (WebAssembly): Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 12.02.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами и вызывать обработчики событий столкновения. . . .
SDL3 для Web (WebAssembly): Загрузка PNG с прозрачным фоном с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 11.02.2026
Содержание блога Библиотека SDL3 содержит встроенные инструменты для базовой работы с изображениями - без использования библиотеки SDL3_image. Пошагово создадим проект для загрузки изображения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru