GLSL смешивает базовую текстуру с текстурой в нужном месте - PullRequest
0 голосов
/ 02 апреля 2012

Допустим, мы текстурируем четырехугольник (два треугольника).Я думаю, что этот вопрос похож на разбрызгивание текстуры, как в следующем примере

precision lowp float;

uniform sampler2D Terrain;
uniform sampler2D Grass;
uniform sampler2D Stone;
uniform sampler2D Rock;

varying vec2 tex_coord;

void main(void)
{
vec4 terrain = texture2D(Terrain, tex_coord);
vec4 tex0    = texture2D(Grass, tex_coord * 4.0); // Tile
vec4 tex1    = texture2D(Rock,  tex_coord * 4.0); // Tile
vec4 tex2    = texture2D(Stone, tex_coord * 4.0); // Tile

tex0 *= terrain.r; // Red channel - puts grass
tex1 = mix( tex0, tex1, terrain.g ); // Green channel - puts rock and mix with grass 
vec4 outColor = mix( tex1, tex2, terrain.b ); // Blue channel - puts stone and mix with others

gl_FragColor = outColor; //final color
}

Но я хочу просто разместить 1 наклейку на базовой текстуре квадра в нужном месте.
Алгоритм такой же, ноя думаю, что нам не нужна дополнительная текстура с 1 заполненным слоем для хранения позиций (например, где красный слой! = 0) декаля, как мы должны сгенерировать нашу собственную переменную "terrain.r" (это float?) и смешать базуТекстура и текстура с ним.

precision lowp float;

uniform sampler2D base;
uniform sampler2D decal;
uniform vec2 decal_location; //where we want place decal (e.g. 0.5, 0.5 is center of quad)

varying vec2 base_tex_coord;
varying vec2 decal_tex_coord;

void main(void)
{
vec4 v_base = texture2D(base, base_tex_coord);
vec4 v_decal = texture2D(Grass, decal_tex_coord);
float decal_layer = /*somehow get our decal_layer based on decal_position*/

gl_FragColor = mix(v_base, v_decal, decal_layer);
}

Как этого добиться?
Или я могу просто сгенерировать текстуру сплата на стороне opengl и передать ее первому шейдеру?Это даст мне до 4 различных наклеек на квадроциклах, но будет частым обновлением (например, попадание пулемета в стену)

Ответы [ 2 ]

2 голосов
/ 02 апреля 2012
float decal_layer = /*somehow get our decal_layer based on decal_position*/

Ну, это зависит от вас, как вы интерпретируете decal_position. Я думаю, что простой метрики расстояния будет достаточно. но для этого также требуется размер четырехугольника. Предположим, вы предоставили это через дополнительную униформу decal_radius. Тогда мы можем использовать

decal_layer = clamp(length(decal_position - vec2(0.5, 0.5)) / decal_radius, 0., 1.);
1 голос
/ 02 апреля 2012

Да, decal_layer - это float, как вы описали. Диапазон значений от 0 до 1. Но у вас недостаточно информации, здесь вы указали decal_location, но не указали размер для декали. Вы также не знаете, где этот фрагмент находится в квадре, вам понадобится varying vec2 quad_coord; или аналогичный вход от вершинного шейдера, если вы хотите знать, где этот фрагмент относительно визуализируемого квада.

Но давайте попробуем другой подход. Отредактируйте верхнюю часть вашего 2-го примера, чтобы включить эту форму:

uniform vec2 decal_location; // Location of decal relative to base_tex_coord uniform float decal_size; // Size of decal relative to base_tex_coord

Теперь в main () вы можете вычислить decal_layer примерно так:

float decal_layer = 1.0 - smoothstep(decal_size - 0.01, decal_size, max(abs(decal_location.x - base_tex_coord.x), abs(decal_location.y - base_tex_coord.y)));

По сути, вы пытаетесь получить decal_layer равным 1,0 внутри декали и 0,0 вне декали. Я добавил нечеткий край 0,01 на границе, с которой вы можете играть. Удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...