2013-09-01 4 views
2

В моей игре на основе 2D-плитки игрок может рисовать плитки, чтобы изменить цвет. Простой подход (и то, что я уже сделал) заключается в использовании параметра tint в SpriteBatch.Draw.Не окрашивайте, но «раскрашивайте» спрайт

Это выглядит красиво, а вот пример:

enter image description here

Но сказать, я хочу, чтобы нарисовать дерево белый. Если вы когда-либо сталкивались с оттенком, вы знаете, что это невозможно с использованием параметра оттенка. Color.White оттеняет цвет спрайта по умолчанию, а не белый. Это не серьезная проблема, но я полагаю, что некоторые пользователи могут этого захотеть.

Мой вопрос: есть ли способ окраски спрайта на основе оттенка/насыщенности вместо оттенка. Подобно функции «colorify» в GIMP.

http://gyazo.com/eaa8d54d82a15ce05b006b084e71803f.png

Очевидный подход будет в том, чтобы использовать эту функцию в GIMP и просто экспортировать спрайты для каждого цвета. Проблема заключается в том, что для всех моих спрайтов это займет много времени, и каждый спрайт имеет несколько вариантов, что означает, что вы могли бы иметь всего 100+ комбо для одного типа блоков.

Возможно ли это? Я предполагаю, что шейдер может выполнить эту работу.

+4

Почему вы не делаете базовый спрайт максимально ярким (почти белый)? Вы можете добиться произвольных эффектов с помощью пиксельного шейдера, но я сомневаюсь, что это необходимо в этом случае. На мой взгляд, Gimp использует ту же технику, что и параметр оттенка. –

+0

Посмотрите на цветовую модель HSV: [link] (http://en.wikipedia.org/wiki/HSL_and_HSV). Вы можете преобразовать текстуру из RGB в HSV, применить смещение к оттенку для изменения цвета, а затем преобразовать его обратно в RGB. Хотя, безусловно, было бы проще просто сделать вашу текстуру яркой белой, чтобы начать, и использовать встроенную тонировку XNA. – foolmoron

ответ

4

Функция «colourify» в GIMP просто делает desaturate (преобразование в оттенки серого), за которым следует умножение цвета. Очень просто. Это должно быть эквивалентно HLSL (непроверенные):

float4 original = tex2d(...); 
float q = (original.r + original.g + original.b)/3; 
q /= original.a; // optional - undo alpha premultiplication 
return float4(tint.rgb * q, tint.a * original.a); 

Но вы могли бы достичь того же эффекта, просто хранить все ваши текстуры ненасыщенный, чтобы начать с и использовать шейдер по умолчанию SpriteBatch для его размножения. Если вы не хотите изменять исходное искусство, вы можете сделать это в специальном обработчике контента.


Хотя, если вы хотите использовать пользовательский шейдер, вы можете сделать что-то более сложное. Вы можете реализовать полный поворот цвета (видный комплекс). Но, возможно, вы могли бы рассмотреть что-то вроде "Overlay" blend mode (очень простое), которое позволяет вам окрашивать серые оттенки, сохраняя как подсветку, так и подсветку (вместо того, чтобы размножаться, что также колорит блики).

+0

При использовании этой формулы на одном и том же пикселе многократно и сохраняя результат в этом пикселе, пиксель становится темнее и темнее. Предложения о том, как избежать этого? – jjxtra

+0

@PsychoDad Если вы не делаете что-то странное с альфа-пре-умножением, то это, вероятно, проблема с потерями точности. Математика с плавающей запятой редко дает точные результаты, а крошечные ошибки в конечном итоге могут привести к большой ошибке. Простой ответ: «не делай этого». Если он все еще вызывает у вас проблемы, может быть, новый вопрос будет полностью детализирован (возможно, на сайте GameDev). –

1

Чтобы продолжить использовать оттенок в SPriteBatch.Draw. Просто сделайте свои «красящие» текстуры полутонами. Таким образом, белый цвет будет вашим дефолтом, но вы рисуете его с оттенком, который делает его по-деревенски.

Я часто использую это, чтобы сделать пользовательский интерфейс и команда раскраски :)

в случае, интересно, что оттенок делает это просто умножить каждый пиксель текстуры по цвету вы выбираете.

пример:
текстуры пиксель (RGBA) [1,0, 0,5, 0,5, 1,0]
оттенок [1,0, 0,5, 0,5, 0,5]
результат [1,0, 0,25, 0,25, 0,5] (наполовину прозрачным и более красным)

+0

Проблема с этим, скажем, у меня есть блок, который не может иметь коричневый оттенок, применяемый по умолчанию, блок с несколькими цветами. Я мог бы просто захватить данные texture2d и скопировать его в новый как полутоновый. – Cyral

+0

@CYral Если это так, я мог бы подумать о том, что у меня есть метод Paint (Color tintColor), который получил версию исходной текстуры в оттенках серого и подкрасил ее (было бы легко сделать с помощью rendertarget). –